home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************************************************************************/
- /* File : EASYWAD.C */
- /* Executable : EASYWAD.EXE */
- /* Helpfile : EASYWAD.CFG */
- /* Doc file : EASYWAD.DOC */
- /* Version num : 1.05 */
- /* Last changed : 08-09-1994 22:24 */
- /* Update count : 9 */
- /* OS type : PC (DOS) */
- /* Description : Menu handler for multiple WAD files for DOOM (Trademark of Id Software) */
- /* Compiler : Microsoft (R) Quick C Compiler Version 2.00 */
- /* Linker : Microsoft (R) QuickC Linker Version 4.06 */
- /* QCL attribs : /AC /G2 /Ot /Zr (Compact model, optimized 80286 code, enable pointer checking) */
- /* Other : WM.BAT : start file */
- /* START.BAT : the result */
- /* Remarks : Credits go to Brendon Wyber & Raphael Quinet (Doom Editor Utilities) for WadHeader and WadDirectory structures */
- /* and the THING_... defines. */
- /* */
- /* By M. van der Heide of ThunderWare Research Center */
- /**********************************************************************************************************************************/
-
- #include <bios.h>
- #include <ctype.h>
- #include <direct.h>
- #include <dos.h>
- #include <graph.h>
- #include <malloc.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <search.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define boolean char
- #define TRUE 1
- #define FALSE 0
-
- #define DBLACK 0 /* Define names for the standard (VGA) palette colors */
- #define DBLUE 1
- #define DGREEN 2
- #define DCYAN 3
- #define DRED 4
- #define DMAGENTA 5
- #define DYELLOW 6
- #define DWHITE 7
- #define LBLACK 8
- #define LBLUE 9
- #define LGREEN 10
- #define LCYAN 11
- #define LRED 12
- #define LMAGENTA 13
- #define LYELLOW 14
- #define LWHITE 15
-
- #define ANYATTR _A_NORMAL|_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_ARCH /* File attributes */
- #define SUBATTR _A_NORMAL|_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_ARCH|_A_SUBDIR /* Subdirectory attributes */
- #define MAXWADS 1000 /* Max number of WAD files the program can handle */
- #define MAXAUTOINCLUDE 5 /* Maximum number of autoinclude-WAD files in a CONFIGFILE */
- #define MAXWADDIRS 400 /* Max number of WAD file directories a CONFIGFILE may contain */
- #define PAGE 60 /* Max number of WAD files on screen */
- #define WADHEIGHT 20 /* Max number of filenames vertically */
- #define WADWIDTH 27 /* Max positions taken for a filename+info horizontally */
- #define MAXINFOLEN 16 /* Max length of a WAD file info field */
- #define ENTRYLEN 8 /* Length of the name of a 'directory' entry in a WAD file */
- #define NOMEM (void far *)0 /* Memory allocation error */
-
- #define DEFAULTCONFIGFILE "EASYWAD.CFG"
- #define COMMENT '#' /* All characters in a line following this one are ignored in a CONFIGFILE */
- #define DEFAULTWADDIR "." /* Current directory */
- #define DEFAULTINFOFILE "WADS.DSC"
- #define WADFILE "*.WAD"
- #define BATFILE "START.BAT" /* This file is built at the end */
- #define RESPONSEFILE "START.OPT" /* Response file if DOOMVERSION is 1.5 or higher */
- #define DOSUB1 "/S" /* Used in CONFIGFILE in a WADDIR entry: do subdirs too */
- #define DOSUB2 "-S"
- #define RESCAN1 "/R" /* Used on the command line: rebuild WAD InfoFile */
- #define RESCAN2 "-R"
- #define OTHERCONFIGFILE '+' /* Used on the command line: use other config file than EASYWAD.CFG */
-
- #define MAINWAD1 "DOOM.WAD" /* Main WAD file (registered version) */
- #define MAINWAD2 "DOOM1.WAD" /* Main WAD file (shareware version) */
-
- #define STARTALONE "DOOM" /* Define the start commands for DOOM */
- #define STARTIPX "IPXSETUP"
- #define STARTLINK "SERSETUP"
- #define DMATCH "-DEATHMATCH" /* Define the command parameters for DOOM */
- #define INCFILE "-FILE"
- #define DEVPARM "-DEVPARM"
- #define GOTOEPISODE "-EPISODE"
- #define GOTOANYTHING "-WART"
- #define SKILL "-SKILL"
- #define NUMPLAYERS "-NODES"
- #define COMPORT "-COM"
-
- #define NOFIELD 0 /* Number the FIELDs on the screen */
- #define FILEFIELD 1
- #define EPISODEFIELD 2
- #define DIFFICULTYFIELD 3
- #define PLAYTYPEFIELD 4
- #define LEVELFIELD 5
- #define DEATHMATCHFIELD 6
- #define PAGERFIELD 7
- #define RDPREVFIELD 8
- #define STARTFIELD 9
- #define AUTOMATICFIELD 10
-
- #define DEFAULTVERSION 0 /* This effectively means 1.0 */
- #define DEFAULTEPISODE 1
- #define DEFAULTDIFFICULTY 3
- #define DEFAULTPLAYTYPE 1
- #define DEFAULTLEVEL 1
- #define DEFAULTDMATCH FALSE
- #define DEFAULTNODES 2
- #define DEFAULTCOMPORT 1
-
- #define KEY_EPISODE 'E' /* Keyboard equivalents of mouse selections */
- #define KEY_LEVEL 'L'
- #define KEY_DIFFICULTY 'S' /* (Skill) */
- #define KEY_PLAYTYPE 'T'
- #define KEY_NODES 'N'
- #define KEY_COMPORT 'C'
- #define KEY_DEATHMATCH 'D'
- #define KEY_AUTO 'A'
- #define KEY_READPREVIOUS 'R'
- #define KEY_ABORT 0x1B /* [ESC] */
- #define KEY_STARTGAME 0x0D /* [RETURN] */
- #define KEY_PAGEUP 0x4900
- #define KEY_PAGEDOWN 0x5100
- #define KEY_CURSLEFT 0x4B00
- #define KEY_CURSRIGHT 0x4D00
- #define KEY_CURSUP 0x4800
- #define KEY_CURSDOWN 0x5000
- #define KEY_SELECTFILE 0x3900 /* [SPACE] */
-
- #define EXCL_NONE 0 /* Define exclude types for (following) ExtCom_s structure */
- #define EXCL_NIGHTMARE 1
- #define EXCL_NOTDMATCH 2
-
- #define RETURNERROR 1 /* Define exit codes */
- #define RETURNABORT 1
- #define RETURNSTART 0
-
- #define NUMEPISODE 3 /* Define the number of possible episodes */
- #define NUMLEVEL 9 /* Define the number of possible levels */
- #define NUMDIFFICULTY 5
- #define NUMPLAYTYPE 3
-
- #define LO_EPIS '0' /* First episode number - 1 (char) */
- #define HI_EPIS LO_EPIS + NUMEPISODE /* Last episode number (char) */
- #define LO_LEVL '0'
- #define HI_LEVL LO_LEVL + NUMLEVEL
- #define LO_DIFF '0'
- #define HI_DIFF LO_DIFF + NUMDIFFICULTY
- #define LO_COMM '0'
- #define HI_COMM '4'
- #define LO_NODE '2'
- #define HI_NODE '4'
-
- #define MAXIGNORE 12 /* Define number of WAD 'directory' identifiers per type */
- #define MAXCOLORS 2
- #define MAXDEMOS 1
- #define MAXLEVELS NUMEPISODE * NUMLEVEL
- #define MAXSPRITES 78
- #define MAXSOUNDS 2
- #define MAXMUSIC 3
- #define MAXGRAPHS 0
- #define MAXADDSWITCHES 9
-
- #define NEWCOLORS 0x01 /* Define bits for the 'NewStuff' field in the 'wadinfo' structure */
- #define NEWDEMOS 0x02
- #define NEWSOUNDS 0x04
- #define NEWMUSIC 0x08
- #define NEWSPRITES 0x10
- #define NEWGRAPHS 0x20
-
- #define ToNumber(_Drv) (toupper ((_Drv)) - 'A' + 1) /* Convert drive name to drive number */
- #define ToName(_Drv) ((_Drv) + 'A' - 1) /* Convert drive number to drive name */
-
- struct Mouse_s /* Define mouse info */
- {
- int OldXx; /* Coordinates stored from previous status check */
- int OldYy;
- int Xx; /* 0 - 79 */
- int Yy; /* 0 - 29 */
- boolean CoChange; /* TRUE if coordinates have chenged (mouse moved to a next character) */
- boolean Left; /* Status of the 3 mouse buttons; TRUE if pressed */
- boolean Middle;
- boolean Right;
- boolean LeftStillPressed; /* TRUE if the left button was also pressed in previous status check */
- } Mouse;
-
- struct WadDir_s /* Define info for a WADDIR entry */
- {
- char Drive; /* 1 = A, etc., 0 means: no drive given */
- char Name[_MAX_DIR];
- boolean DoSubDirs; /* TRUE if the subdirectories should be searched as well */
- };
-
- struct WadInfo_s /* Define info for a WADFILE entry (also used for AUTOINCLUDE files) */
- {
- char Name[_MAX_FNAME]; /* Filled out, no extension (as this is always *.WAD) */
- char Info[MAXINFOLEN + 1]; /* Info as found in a WADINFOFILE file */
- char Drive; /* 1 = A, etc., 0 means: no drive given */
- char Path[_MAX_DIR];
- char OrigName[_MAX_FNAME + _MAX_EXT - 1]; /* The original name, with extension */
- char NewStuff; /* Each bit represents an identifier type (demo, sound, etc) */
- long NewLevels; /* Each bit represents a level: */
- /* bits 0- 8 = episode 1 */
- /* bits 9-17 = episode 2 */
- /* bits 18-26 = episode 3 */
- /* bits 27-31 = unused */
- boolean Selected; /* TRUE if the WAD is selected on screen */
- };
-
- struct WadHeader_s /* The first 12 bytes of a WAD file */
- {
- char Type[4]; /* "PWAD" for a patch WAD, "IWAD" for an initial WAD */
- long DirSize; /* Number of entries in the WAD 'directory' */
- long DirStart; /* Pointer to the location (offset) of the 'directory' in the WAD file */
- };
-
- struct WadDirectory_s /* A 'directory' entry in the WAD file */
- {
- long Start; /* Pointer to the data of this entry in the WAD file */
- long Size; /* Length in bytes of the data */
- char Name[ENTRYLEN]; /* Identifier (name) of this entry */
- };
-
- struct ExtCom_s
- {
- char *Command;
- int VersionNeeded;
- boolean InUse;
- char ExcludeType;
- boolean DevparmNeeded;
- };
-
- struct WadDir_s far *WadDir[MAXWADDIRS];
- struct WadInfo_s far *WadInfo[MAXWADS];
- struct WadInfo_s far *AutoInc[MAXAUTOINCLUDE];
-
- char CurPath[_MAX_DIR]; /* Current directory (preceded by drive:) */
- char ConfigFile[_MAX_PATH]; /* Filename of the CONFIGFILE */
- char InfoFile[_MAX_PATH]; /* Filename of WADINFOFILE as found in the CONFIGFILE */
- char DoomDirectory[_MAX_PATH]; /* The main DOOM directory as found in the CONFIGFILE */
- char S[256]; /* All-purpose string */
- char CurrentField; /* Current FIELD type (see defines) */
- char SelectionChange; /* Used in file FIELD; TRUE if selection toggled */
- char CurrentPage; /* Current file FIELD page */
- int CurDrive; /* Current drive */
- int DoomDrive; /* Drive of main DOOM directory */
- int TotalWads; /* Total number of found WAD files */
- int TotalWadDirs; /* Total number of read WADDIR entries in the CONFIGFILE */
- int TotalAutoInc; /* Total number of read AUTOINCLUDE entries in a CONFIGFILE */
- int M;
- int N;
- int Dummy; /* Used in _dos_setdrive function */
- boolean UseMouse; /* TRUE if a mouse has been found */
- boolean MouseHidden; /* TRUE if the mouse pointer is temporarely hidden */
- boolean Rescan = FALSE; /* TRUE if '-R' was given on the command line */
- boolean ConfigChange = FALSE; /* TRUE if a different CONFIGFILE was given on the command line */
- boolean ScreenOpen = FALSE;
- boolean DoNotSearch = FALSE; /* TRUE if NOSEARCH was found in the CONFIGFILE */
- boolean SortWADFiles = FALSE; /* TRUE if SORTFILES was found in the CONFIGFILE */
- boolean SortByName = TRUE; /* TRUE for "NAME", FALSE for "INFO" */
-
- char CurrentSelected = 0; /* Current pointed WAD file, 0 if none */
- char PreviousWad = 0; /* Previous pointed WAD file, 0 if none */
- char EpisodeActive = DEFAULTEPISODE; /* Initialize selection FIELDs */
- char DifficultyActive = DEFAULTDIFFICULTY;
- char PlayTypeActive = DEFAULTPLAYTYPE;
- char NumNodesActive = DEFAULTNODES;
- char CommPortActive = DEFAULTCOMPORT;
- char CurrentLevel = DEFAULTLEVEL;
- boolean DeathmatchOn = DEFAULTDMATCH;
- int DoomVersion = DEFAULTVERSION; /* 'DoomVersion' holds the decimal 0, 1, 2, 4, 5, 6 or 666 */
-
- char *Episodes[] = {"Knee-Deep in the Dead", "The Shores of Hell ", "Inferno "};
- char *Difficulties[] = {"I'm too young to die ", "Hey, not too rough ", "Hurt me plenty ", "Ultra-Violence! ",
- "NIGHTMARE "};
- char *PlayTypes[] = {"Alone ", "IPX-compatible ", "Null-modem link "};
- char *NumberNodes = "Number of players ";
- char *CommPort = "COM port ";
- char *Level = "LEVEL ";
- char *Deathmatch = "DEATHMATCH! ";
- char *Boxes[] = {"[ ] ", "[X] "};
- char *PreviousPage = "<<<";
- char *NextPage = ">>>";
- char *StartGame = "[START]";
- char *ReadPrevious = "[READ PREVIOUS]";
- char *Automatic = "[AUTO]";
-
- char *IdIgnore[] = {"THINGS", "LINEDEFS", "SIDEDEFS", "VERTEXES", "SEGS", "SSECTORS", "NODES", "SECTORS", "REJECT",
- "BLOCKMAP", "INFOPACK", "PLATFORM", " "}; /* Last 2 are NOT from Id Software! */
- char *IdColors[] = {"PLAYPAL", "COLORMAP", "c", "palette"};
- char *IdDemos[] = {"DEMO", "d", "demos"};
- char *IdLevels[] = {"E1M1", "E1M2", "E1M3", "E1M4", "E1M5", "E1M6", "E1M7", "E1M8", "E1M9",
- "E2M1", "E2M2", "E2M3", "E2M4", "E2M5", "E2M6", "E2M7", "E2M8", "E2M9",
- "E3M1", "E3M2", "E3M3", "E3M4", "E3M5", "E3M6", "E3M7", "E3M8", "E3M9", "E", "M"};
- char *IdSprites[] = {"SARG", "TROO", "BOSS", "PLAY", "POSS", "SPOS", "SKUL", "HEAD", "CYBR", "SPID", "CHG", "SAW",
- "PIS", "PBU", "PSH", "BAL", "PUF", "BLU", "MIS", "TFO", "PUN", "SHT", "PLS", "BFG",
- "BFS", "BFE", "POL", "CAND", "CBRA", "SHOT", "MGUN", "LAUN", "CSAW", "CLIP", "SHEL", "ROCK",
- "STIM", "MEDI", "ARM", "BAR", "COLU", "BPAK", "BROK", "AMMO", "SBOX", "ELEC", "BKEY", "YKEY",
- "RKEY", "SUIT", "PVIS", "BEXP", "PMAP", "PIN", "BON", "SOUL", "TRED", "POL", "COL", "FSKU",
- "CEYE", "TRE", "SMI", "BSKU", "RSKU", "YSKU", "TRE", "PLAS", "BFUG", "CELL", "PSTR", "CELP",
- "GOR", "TGRN", "TBLU", "SMRT", "SMBT", "SMGT", "p", "sprites"};
- char *IdSounds[] = {"DS", "DP", "s", "sounds"};
- char *IdMusic[] = {"D_", "GENMIDI", "DMXGUS", "m", "music"};
- char *IdGraphics[] = {"g", "graphics"};
-
- struct ExtCom_s ExtCom[] = {{"-NOMONSTERS", 2, FALSE, EXCL_NONE, TRUE},
- {"-RESPAWN", 2, FALSE, EXCL_NIGHTMARE, TRUE},
- {"-NOJOY", 2, FALSE, EXCL_NONE, FALSE},
- {"-NOMOUSE", 2, FALSE, EXCL_NONE, FALSE},
- {"-NOMUSIC", 2, FALSE, EXCL_NONE, FALSE},
- {"-NOSFX", 2, FALSE, EXCL_NONE, FALSE},
- {"-NOSOUND", 2, FALSE, EXCL_NONE, FALSE},
- {"-ALTDEATH", 5, FALSE, EXCL_NOTDMATCH, FALSE},
- {"-FAST", 5, FALSE, EXCL_NIGHTMARE, TRUE}};
- int ResetMouse (void)
-
- /**********************************************************************************************************************************/
- /* Pre : None. */
- /* Post : The mouse driver has been reset. If no mouse was found, then 0 is returned. Anything else means success. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- int Result;
-
- _asm
- {
- mov ax, 0x0000
- int 0x33
- mov Result, ax
- }
- return (Result);
- }
-
- void ShowMouse (void)
-
- /**********************************************************************************************************************************/
- /* Pre : (global) 'UseMouse' is TRUE if a mouse has been detected. */
- /* Post : The mouse pointer is made visable. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (UseMouse)
- _asm
- {
- mov ax, 0x0001
- int 0x33
- }
- }
-
- void HideMouse (void)
-
- /**********************************************************************************************************************************/
- /* Pre : (global) 'UseMouse' is TRUE if a mouse has been detected. */
- /* Post : The mouse pointer is made invisable. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (UseMouse)
- _asm
- {
- mov ax, 0x0002
- int 0x33
- }
- }
-
- void MouseStatus (void)
-
- /**********************************************************************************************************************************/
- /* Pre : None. */
- /* Post : The mouse driver has been read, which returns the status of the buttons and the x and y coordinates of the mouse. */
- /* All this information is stored in the 'Mouse' structure. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- int Result;
-
- Mouse.LeftStillPressed = Mouse.Left;
- _asm
- {
- mov ax, 0x0003
- int 0x33
- mov Mouse.Xx, cx
- mov Mouse.Yy, dx
- mov Result, bx
- }
- Mouse.Left = (Result & 0x0001); /* Store the status of the mouse buttons */
- Mouse.Right = (Result & 0x0002);
- Mouse.Middle = (Result & 0x0004);
- Mouse.Xx /= 0x0008; /* Convert pixel coordinates to line coordinates */
- Mouse.Yy /= 0x0010;
- Mouse.CoChange = (Mouse.OldXx != Mouse.Xx || Mouse.OldYy != Mouse.Yy);
- if (!Mouse.Left)
- Mouse.LeftStillPressed = FALSE;
- }
-
- void DeAllocateAll (void)
-
- /**********************************************************************************************************************************/
- /* Pre : None. */
- /* Post : If any WadDirs were initialized yet, then the memory is deallocated completely. */
- /* If any WadInfos were initialized yet, then the memory is deallocated completely. */
- /* If any AutoIncs were initialized yet, then the memory is deallocated completely. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- fcloseall ();
- flushall ();
- while (-- TotalWadDirs >= 0)
- _ffree (WadDir[TotalWadDirs]);
- while (-- TotalWads >= 0)
- _ffree (WadInfo[TotalWads]);
- while (-- TotalAutoInc >= 0)
- _ffree (AutoInc[TotalAutoInc]);
- }
-
- void Bye (int ReturnType, char *Message, ...)
-
- /**********************************************************************************************************************************/
- /* Pre : 'ReturnType' holds the exit code, 'Message' holds the error message. */
- /* Post : The error message has been printed, all memory is freed and the program has been aborted. */
- /* Import: DeAllocateAll. */
- /**********************************************************************************************************************************/
-
- {
- va_list Args;
-
- if (ScreenOpen) /* Still in graphics mode ? */
- _setvideomode (_DEFAULTMODE); /* Then close the screen */
- va_start (Args, Message);
- vfprintf (stderr, Message, Args); /* Print the (formatted) error message */
- va_end (Args);
- _dos_setdrive (CurDrive, &Dummy); /* Return to home drive and directory */
- chdir (CurPath);
- DeAllocateAll ();
- exit (ReturnType);
- }
-
- void PrText (short UseBox, short Y0, short X0, unsigned char Color, char *Msg, ...)
-
- /**********************************************************************************************************************************/
- /* Pre : 'Y0' and 'X0' hold the coordinates, 'Color' holds the (VGA) color and 'Msg' holds the message to print. */
- /* UseBox < 0: no selection box is printed first; */
- /* UseBox = 0: an empty selection box is printed first; */
- /* UseBox > 0: a filled selection box is printed first; */
- /* Post : If the coordinates were non-zero, then the message is printed at these coordinates in the given color. The coordinates */
- /* are first converted to the pixel coordinates according to the used font. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- char Message[80];
- va_list Args;
-
- va_start (Args, Msg);
- vsprintf (Message, Msg, Args); /* Convert the message into one string */
- va_end (Args);
- _settextposition (Y0, X0);
- _settextcolor (Color);
- if (UseBox == 0)
- _outtext (Boxes[0]);
- if (UseBox > 0)
- _outtext (Boxes[1]);
- _outtext (Message);
- }
-
- void InitVideo (void)
-
- /**********************************************************************************************************************************/
- /* Pre : None. */
- /* Post : A VGA display of 640 x 480 x 16 colors has been opened and the screen has been cleared. */
- /* Import: Bye. */
- /**********************************************************************************************************************************/
-
- {
- if (!_setvideomode (_VRES16COLOR))
- Bye (RETURNERROR, "ERROR - You need a VGA videocard for this utility\n");
- _clearscreen (_GCLEARSCREEN);
- }
-
- char *TestName (char *OldName)
-
- /**********************************************************************************************************************************/
- /* Pre : 'OldName' holds the name to be tested. */
- /* Post : The name is tested. The return value is a string of the (adapted) input with the following specifications: */
- /* - Each part (subdirname) has at most 8 characters, possibly followed by a '.' and at most 3 characters. */
- /* - Each of the characters is valid to the DOS system. */
- /* - Trailing backslashes have been cut, except when it was the only path character. */
- /* Import: Bye. */
- /**********************************************************************************************************************************/
-
- {
- char Level[_MAX_PATH];
- char NewName[_MAX_PATH];
- char Part[_MAX_FNAME];
- int LvlCnt;
- int Ex;
- int PathLenOldName;
- int CharCnt;
- int PartChar;
- boolean PointDone;
- boolean NError = FALSE;
- boolean DriveFound = FALSE;
- boolean Ready = FALSE;
-
- PathLenOldName = strlen (OldName);
- CharCnt = -1;
- NewName[0] = '\0';
- while (!Ready && !NError)
- {
- LvlCnt = 0;
- while ((++ CharCnt < PathLenOldName) && OldName[CharCnt] != '\\' && OldName[CharCnt] != ':')
- Level[LvlCnt ++] = OldName[CharCnt];
- Level[LvlCnt] = '\0';
- if (OldName[CharCnt] == ':') /* Preceded by drive: ? */
- if (DriveFound) /* Already a drive found! */
- NError = TRUE;
- else
- {
- DriveFound = TRUE;
- strncpy (NewName, OldName, CharCnt + 1);
- NewName[CharCnt + 1] = '\0';
- if (CharCnt != 1 || toupper (OldName[0]) < 'A' || toupper (OldName[0]) > 'Z') /* Test drive validity */
- Bye (RETURNERROR, "ERROR - Invalid drivename %s\n", NewName);
- if (CharCnt == PathLenOldName - 1)
- Ready = TRUE; /* Only a driveletter given */
- else
- if (CharCnt == PathLenOldName - 2 && OldName[CharCnt + 1] == '\\')
- {
- Ready = TRUE; /* Exceptional case: only drive:\ given */
- strcpy (NewName, OldName);
- }
- }
- else
- {
- if (CharCnt == PathLenOldName) /* Handling last part ? */
- Ready = TRUE;
- if (CharCnt == PathLenOldName - 1 && OldName[CharCnt] == '\\')
- Ready = TRUE; /* Ended with backslash */
- PointDone = FALSE;
- for (PartChar = 0 ; PartChar < strlen (Level) ; PartChar ++)
- switch (Level[PartChar])
- {
- case '.' : if (!PointDone)
- {
- strncpy (Part, Level, PartChar < 8 ? PartChar : 8);
- Part[PartChar < 8 ? PartChar : 8] = '\0'; /* Cut >8 characters */
- strcat (NewName, Part);
- strcat (NewName, "."); /* Add the '.' */
- Ex = PartChar + 1;
- PointDone = TRUE;
- }
- else
- if (strcmp (Level, "..")) /* Exceptional case */
- NError = TRUE;
- break;
- case ';' :
- case ',' :
- case '\'' :
- case '/' :
- case '(' :
- case ')' :
- case '[' :
- case ']' : /* Characters '>', '<', '|' '"' and '\' have already been taken out */
- case '=' : NError = TRUE; /* All bad characters */
- break;
- }
- if (!PointDone) /* Finish filenames without extension */
- {
- strncpy (Part, Level, PartChar < 8 ? PartChar : 8);
- Part[PartChar < 8 ? PartChar : 8] = '\0';
- strcat (NewName, Part);
- PointDone = TRUE;
- }
- else /* This also deals with the second point in '..' */
- {
- strncpy (Part, Level + Ex, PartChar - Ex < 3 ? PartChar - Ex : 3); /* Cut >3 characters */
- Part[PartChar - Ex < 3 ? PartChar - Ex : 3] = '\0';
- strcat (NewName, Part);
- }
- if (!Ready)
- strcat (NewName, "\\"); /* Add the subdir character */
- }
- }
- if (NError) /* Report bad characters */
- Bye (RETURNERROR, "\nERROR - Invalid name %s\n", OldName);
- if (!strlen (NewName) && OldName[0] == '\\') /* Input was root dir */
- return ("\\"); /* Which should be treated differently */
- else
- return (NewName); /* Return (modified) string */
- }
-
- void GetWadInfo (int WadNumber, boolean GoThere)
-
- /**********************************************************************************************************************************/
- /* Pre : 'WadNumber' holds the WAD file number in memory that should be checked. */
- /* 'GoThere' is TRUE if the routine should first go to the required drive and directory. */
- /* Post : The WAD directory of the file has been found and read out. The structure 'wadinfo' has been updated. */
- /* Import: Bye. */
- /**********************************************************************************************************************************/
-
- {
- FILE *Fp;
- struct WadDirectory_s WadDirectory;
- struct WadHeader_s WadHeader;
- char Identifier[9];
- char DrivePath[_MAX_DIR];
- int O;
- long Entries;
- boolean More;
-
- if (GoThere) /* Jump to the directory if needed */
- {
- _dos_setdrive (WadInfo[WadNumber]->Drive, &Dummy);
- free (getcwd (DrivePath, _MAX_DIR - 1)); /* Collect current directory */
- chdir (WadInfo[WadNumber]->Path);
- }
- if (!(Fp = fopen (WadInfo[WadNumber]->OrigName, "rb")))
- Bye (RETURNERROR, "ERROR - Error opening file %s\n", WadInfo[WadNumber]->OrigName);
- if (fread (&WadHeader, 1, sizeof (struct WadHeader_s), Fp) != sizeof (struct WadHeader_s)) /* Read the WAD header */
- Bye (RETURNERROR, "ERROR - Error reading file %s\n", WadInfo[WadNumber]->OrigName);
- if (strncmp (WadHeader.Type, "PWAD", 4) && strncmp (WadHeader.Type, "IWAD", 4)) /* Is it a WAD file ? */
- Bye (RETURNERROR, "ERROR - File %s is not a WAD file\n", WadInfo[WadNumber]->OrigName);
- if (fseek (Fp, WadHeader.DirStart, SEEK_SET)) /* Go to the WAD 'directory' part of the file */
- Bye (RETURNERROR, "ERROR - Error reading file %s\n", WadInfo[WadNumber]->OrigName);
- WadInfo[WadNumber]->NewStuff = 0x00; /* Clear all entries */
- WadInfo[WadNumber]->NewLevels = 0x00000000;
- Entries = -1; /* Count all WAD 'directory' entries */
- while (++ Entries < WadHeader.DirSize) /* The number of entries was found in the WAD header */
- {
- if (fread (&WadDirectory, 1, sizeof (struct WadDirectory_s), Fp) != sizeof (struct WadDirectory_s)) /* Read an entry */
- Bye (RETURNERROR, "ERROR - Error reading file %s\n", WadInfo[WadNumber]->OrigName);
- for (O = 0 ; O < ENTRYLEN ; O ++) /* Fill the identifier to 8 positions */
- Identifier[O] = WadDirectory.Name[O];
- Identifier[ENTRYLEN] = '\0'; /* And make it a string */
- More = TRUE; /* Now test it against all types and signal successes */
- for (O = 0 ; O < MAXIGNORE && More ; O ++)
- if (!strnicmp (Identifier, IdIgnore[O], strlen (IdIgnore[O])))
- More = FALSE;
- if (More)
- for (O = 0 ; O < MAXCOLORS && More ; O ++)
- if (!strnicmp (Identifier, IdColors[O], strlen (IdColors[O])))
- {
- More = FALSE;
- WadInfo[WadNumber]->NewStuff |= NEWCOLORS;
- }
- if (More)
- for (O = 0 ; O < MAXDEMOS && More ; O ++)
- if (!strnicmp (Identifier, IdDemos[O], strlen (IdDemos[O])))
- {
- More = FALSE;
- WadInfo[WadNumber]->NewStuff |= NEWDEMOS;
- }
- if (More)
- for (O = 0 ; O < MAXLEVELS && More ; O ++)
- if (!strnicmp (Identifier, IdLevels[O], strlen (IdLevels[O])))
- {
- More = FALSE;
- WadInfo[WadNumber]->NewLevels |= ((long)1 << O);
- }
- if (More)
- for (O = 0 ; O < MAXSPRITES && More ; O ++)
- if (!strnicmp (Identifier, IdSprites[O], strlen (IdSprites[O])))
- {
- More = FALSE;
- WadInfo[WadNumber]->NewStuff |= NEWSPRITES;
- }
- if (More)
- for (O = 0 ; O < MAXSOUNDS && More ; O ++)
- if (!strnicmp (Identifier, IdSounds[O], strlen (IdSounds[O])))
- {
- More = FALSE;
- WadInfo[WadNumber]->NewStuff |= NEWSOUNDS;
- }
- if (More)
- for (O = 0 ; O < MAXMUSIC && More ; O ++)
- if (!strnicmp (Identifier, IdMusic[O], strlen (IdMusic[O])))
- {
- More = FALSE;
- WadInfo[WadNumber]->NewStuff |= NEWMUSIC;
- }
- if (More && WadDirectory.Start != NULL && Identifier[0] != '\0') /* All other identifiers are counted as graphics */
- WadInfo[WadNumber]->NewStuff |= NEWGRAPHS;
- }
- fclose (Fp);
- if (GoThere)
- {
- chdir (DrivePath);
- _dos_setdrive (CurDrive, &Dummy); /* Return to home location */
- }
- }
-
- void WriteWadInfo (char *FileName)
-
- /**********************************************************************************************************************************/
- /* Pre : 'FileName' holds the name of the file (which is the same as set in 'InfoFile'). */
- /* Post : All found WAD files are considered. All files have their fields 'NewStuff' and 'NewLevels' initialized. This info is */
- /* converted into readable text and written to the file, together with the path information of the WAD file. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- FILE *Fp;
- char Memory;
- char P;
- char Q;
- char T[81];
- int WadNumber;
- boolean First;
- boolean New;
- boolean More;
-
- if (!(Fp = fopen (FileName, "w")))
- Bye (RETURNERROR, "ERROR - Cannot write WAD info file\n");
- for (WadNumber = 0 ; WadNumber < TotalWads ; WadNumber ++)
- {
- More = FALSE;
- S[0] = '\0';
- fprintf (Fp, "%d %s %s ", WadInfo[WadNumber]->Drive, WadInfo[WadNumber]->Path, WadInfo[WadNumber]->OrigName);
- More = (WadInfo[WadNumber]->NewLevels != 0x00000000); /* Are their any patch levels in this file ? */
- if (More) /* Skip if not */
- {
- for (P = 0 ; P < NUMEPISODE ; P ++)
- {
- Memory = -1;
- First = TRUE;
- if ((WadInfo[WadNumber]->NewLevels & ((long)0x1ff << (P * NUMLEVEL))) == ((long)0x1ff << (P * NUMLEVEL)))
- { /* All 9 level-bits of an episode set */
- sprintf (T, "%s%d-", IdLevels[MAXLEVELS], (int)P + 1);
- strcat (S, T);
- }
- else /* Possibly a partial episode */
- for (Q = 0 ; Q < NUMLEVEL ; Q ++) /* Handle all level-bits in this episode */
- if (WadInfo[WadNumber]->NewLevels & ((long)1 << (P * NUMLEVEL + Q)))
- {
- if (Memory == -1)
- if (First)
- {
- sprintf (T, "%s%d%s%d", IdLevels[MAXLEVELS], (int)P + 1, IdLevels[MAXLEVELS + 1], (int)Q + 1);
- strcat (S, T);
- First = FALSE;
- Memory = 1;
- New = FALSE;
- }
- else
- {
- sprintf (T, ",%d", (int)Q + 1);
- strcat (S, T);
- Memory = Q + 1;
- New = FALSE;
- }
- else
- {
- Memory ++;
- New = TRUE;
- }
- }
- else
- {
- if (Memory > 0 && New)
- {
- sprintf (T, "-%d", (int)Memory);
- strcat (S, T);
- }
- Memory = -1;
- }
- if (Memory > 0 && New)
- {
- sprintf (T, "-%d", (int)Memory);
- strcat (S, T);
- }
- }
- sprintf (T, "%-10s", S);
- strcpy (S, T);
- } /* No new levels in this WAD file */
- else /* If only one type was found (for example, only sounds) */
- if (!(WadInfo[WadNumber]->NewStuff ^ NEWCOLORS)) /* Then use the complete word ('sounds' in this example) */
- sprintf (S, "%s", IdColors[MAXCOLORS + 1]);
- else
- if (!(WadInfo[WadNumber]->NewStuff ^ NEWDEMOS))
- sprintf (S, "%s", IdDemos[MAXDEMOS + 1]);
- else
- if (!(WadInfo[WadNumber]->NewStuff ^ NEWSOUNDS))
- sprintf (S, "%s", IdSounds[MAXSOUNDS + 1]);
- else
- if (!(WadInfo[WadNumber]->NewStuff ^ NEWMUSIC))
- sprintf (S, "%s", IdMusic[MAXMUSIC + 1]);
- else
- if (!(WadInfo[WadNumber]->NewStuff ^ NEWSPRITES))
- sprintf (S, "%s", IdSprites[MAXSPRITES + 1]);
- else
- if (!(WadInfo[WadNumber]->NewStuff ^ NEWGRAPHS))
- sprintf (S, "%s", IdGraphics[MAXGRAPHS + 1]);
- else
- {
- More = TRUE; /* More than one type found */
- sprintf (S, "- "); /* Clear level string-part */
- }
- if (More) /* Levels found or more types than 1 */
- {
- if (WadInfo[WadNumber]->NewStuff & NEWCOLORS) /* Print one character to indicate the type */
- strcat (S, IdColors[MAXCOLORS]);
- if (WadInfo[WadNumber]->NewStuff & NEWDEMOS)
- strcat (S, IdDemos[MAXDEMOS]);
- if (WadInfo[WadNumber]->NewStuff & NEWSOUNDS)
- strcat (S, IdSounds[MAXSOUNDS]);
- if (WadInfo[WadNumber]->NewStuff & NEWMUSIC)
- strcat (S, IdMusic[MAXMUSIC]);
- if (WadInfo[WadNumber]->NewStuff & NEWSPRITES)
- strcat (S, IdSprites[MAXSPRITES]);
- if (WadInfo[WadNumber]->NewStuff & NEWGRAPHS)
- strcat (S, IdGraphics[MAXGRAPHS]);
- }
- fprintf (Fp, "%-16s\n", S); /* MAXINFOLEN */
- }
- fclose (Fp);
- }
-
- int NextString (FILE *Fp, char *String)
-
- /**********************************************************************************************************************************/
- /* Pre : 'Fp' points to the open CONFIGFILE, 'String' holds the address of the string to be read. */
- /* Post : Any string is read. If it started with a '#' (COMMENT character), then the rest of the line has been ignored. The */
- /* function does not return before a string was read WITHOUT this character or EOF has been reached. The result of the */
- /* function is the length of the read string, or 0 if EOF was encountered. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- char Ch;
- char Cnt;
- boolean Ready = FALSE;
- boolean SkipSpaces;
-
- while (!Ready) /* Read until a valid string is found */
- {
- SkipSpaces = TRUE;
- while (SkipSpaces)
- {
- fscanf (Fp, "%c", &Ch); /* Read until no white-spaces found */
- if (feof (Fp))
- {
- String[0] = '\0'; /* Or until EOF */
- return (0);
- }
- SkipSpaces = isspace (Ch);
- }
- if (Ch == COMMENT) /* First character is the COMMENT character ? */
- do
- {
- fscanf (Fp, "%c", &Ch); /* Ignore until end of the line */
- if (feof (Fp))
- {
- String[0] = '\0'; /* Or until EOF */
- return (0);
- }
- }
- while (Ch != '\n');
- else
- Ready = TRUE;
- }
- Cnt = 0;
- while (!isspace (Ch))
- {
- String[Cnt ++] = Ch;
- fscanf (Fp, "%c", &Ch); /* Read until first white-space */
- if (feof (Fp))
- {
- String[Cnt] = '\0'; /* Or until EOF */
- return (Cnt);
- }
- }
- String[Cnt] = '\0';
- return (Cnt);
- }
-
- void ReadConfig (void)
-
- /**********************************************************************************************************************************/
- /* Pre : The (global) 'ConfigFile' should be initialized. */
- /* Post : If a configuration file is found, then it has been read out. Only 8 keywords are recognised: */
- /* - DOOMDIR, after which the name of the main DOOM directory should be given. */
- /* - DOOMVERSION, after which the (float) DOOM version should be typed. */
- /* - WADDIR, after which a maximum of 400 WAD directories may be given; If an entry '/S' or '-S' is encountered, then all */
- /* subdirectories of the previously declared directory will also be used as WADDIRs. */
- /* - WADINFOFILE, after which a WAD info file may be given. All simple errors are reported. */
- /* */
- /* If one (or all) are not found, then they are initialized with the defaults. */
- /* */
- /* - SETSKILL, after which the default skill (1-5) must be given. */
- /* - DEATHMATCH (no parameters). This means that deathmatch will be set as default. */
- /* - AUTOINCLUDE, after which a maximum of 5 WAD files (complete with (partial) path) may be given. These files will then */
- /* automatically be selected when starting. If the file is not crossed when reading the directories (WADDIRs), then the */
- /* file is just not selected (no error will be generated). */
- /* - NOSEARCH (no parameters). If this keyword is given, then the program will not search all given WADDIR directories, */
- /* it will use the WADINFOFILE instead and use all named entries instead. (This should be used with caution!) */
- /* - SETCOMPORT, after which the default COM port (1-4) must be given for null-modem link. */
- /* - SETNODES, after which the default number of players (2-4) must be given for IPX link. */
- /* - SETPLAYTYPE, after which one of the keywords "ALONE", "IPX" or "NULL" must be given. */
- /* - ADDSWITCHES, after which all the direct DOOM switches should be typed. */
- /* - SORTFILES, after which one of the keywords "NAME" or "INFO" must be given. */
- /* If a character '#' is encountered, then the rest of this line is ignored (comment). */
- /* Before returning, a test has been made if all selected switches are implemented in the given DOOM version. */
- /* Import: NextString. */
- /**********************************************************************************************************************************/
-
- {
- FILE *Fp;
- char DrivePath[_MAX_DIR];
- char Item[256];
- int DriveNo;
- boolean DirsDefined = FALSE;
- boolean InfoDefined = FALSE;
- boolean DoomDefined = FALSE;
- boolean DVerDefined = FALSE;
- boolean DriveChanged;
-
- TotalWadDirs = 0;
- TotalAutoInc = 0;
- if (Fp = fopen (ConfigFile, "r")) /* Skip if no CONFIGFILE was found */
- {
- NextString (Fp, Item); /* Read-ahead first string: must be a keyword */
- while (!feof (Fp))
- {
- if (!stricmp (Item, "DOOMDIR"))
- {
- DoomDefined = TRUE; /* Signal: main DOOM directory has been defined */
- NextString (Fp, Item);
- if (!strlen (Item))
- Bye (RETURNERROR, "ERROR - Invalid configuration file\n");
- DriveChanged = FALSE;
- strcpy (S, TestName (Item));
- if (S[1] == ':') /* Preceded by drive: ? */
- {
- if (strlen (S) == 2) /* Just a drive, no path ? */
- Bye (RETURNERROR, "ERROR - Missing path for DOOMDIR in configuration file\n");
- DriveNo = ToNumber (S[0]);
- if (DriveNo != CurDrive) /* A new drive ? */
- {
- _dos_setdrive (DriveNo, &Dummy);
- _dos_getdrive (&Dummy);
- if (Dummy != DriveNo)
- Bye (RETURNERROR, "ERROR - Drive %c in DOOMDIR does not exist\n", ToName (DriveNo));
- DoomDrive = DriveNo; /* Store drive number */
- }
- else
- DoomDrive = 0; /* Signal: no new drive given */
- strcpy (DoomDirectory, strupr (S + 2)); /* Store path */
- }
- else
- {
- DoomDrive = 0; /* Signal: no new drive given */
- strcpy (DoomDirectory, TestName (Item));
- }
- NextString (Fp, Item); /* Read next keyword */
- }
- if (!stricmp (Item, "WADDIR"))
- {
- NextString (Fp, Item); /* Read-ahead first argument */
- while (!feof (Fp)
- && stricmp (Item, "WADINFOFILE")
- && stricmp (Item, "SETSKILL")
- && stricmp (Item, "DEATHMATCH")
- && stricmp (Item, "NOSEARCH")
- && stricmp (Item, "DOOMDIR")
- && stricmp (Item, "SETCOMPORT")
- && stricmp (Item, "SETNODES")
- && stricmp (Item, "SETPLAYTYPE")
- && stricmp (Item, "DOOMVERSION")
- && stricmp (Item, "ADDSWITCHES")
- && stricmp (Item, "SORTFILES")
- && stricmp (Item, "AUTOINCLUDE"))
- {
- if (!stricmp (Item, DOSUB1) || !stricmp (Item, DOSUB2))
- if (!DirsDefined)
- Bye (RETURNERROR, "ERROR - Badly placed switch %s in WADDIR field\n", DOSUB1);
- else
- WadDir[TotalWadDirs - 1]->DoSubDirs = TRUE;
- else
- {
- DirsDefined = TRUE; /* Signal: at least one WADDIR given */
- if (TotalWadDirs == MAXWADDIRS)
- Bye (RETURNERROR, "ERROR - Too many WADDIR entries\n");
- if ((WadDir[TotalWadDirs] = ((struct WadDir_s far *)_fmalloc ((size_t)sizeof (struct WadDir_s)))) == NOMEM)
- Bye (RETURNERROR, "FATAL ERROR - Out of memory\n");
- DriveChanged = FALSE;
- strcpy (S, TestName (Item));
- if (S[1] == ':') /* Preceded by drive: ? */
- {
- if (strlen (S) == 2) /* Just a drive, no path ? */
- Bye (RETURNERROR, "ERROR - Missing path for WADDIR in configuration file\n");
- DriveNo = ToNumber (S[0]);
- if (DriveNo != CurDrive) /* A new drive ? */
- {
- _dos_setdrive (DriveNo, &Dummy);
- _dos_getdrive (&Dummy);
- DriveChanged = (Dummy == DriveNo); /* Check that the change has been made */
- WadDir[TotalWadDirs]->Drive = DriveNo; /* Store drive number */
- }
- else
- WadDir[TotalWadDirs]->Drive = 0; /* Signal: no new drive given */
- strcpy (WadDir[TotalWadDirs]->Name, strupr (S + 2)); /* Store path */
- }
- else
- {
- WadDir[TotalWadDirs]->Drive = 0; /* Signal: no drive given */
- strcpy (WadDir[TotalWadDirs]->Name, strupr (S));
- }
- WadDir[TotalWadDirs]->DoSubDirs = FALSE;
- TotalWadDirs ++;
- if (DriveChanged)
- _dos_setdrive (CurDrive, &Dummy); /* Return to home drive */
- }
- NextString (Fp, Item); /* Read next argument */
- }
- }
- if (!stricmp (Item, "AUTOINCLUDE"))
- {
- NextString (Fp, Item); /* Read-ahead first argument */
- while (!feof (Fp)
- && stricmp (Item, "WADINFOFILE")
- && stricmp (Item, "SETSKILL")
- && stricmp (Item, "DEATHMATCH")
- && stricmp (Item, "NOSEARCH")
- && stricmp (Item, "DOOMDIR")
- && stricmp (Item, "SETCOMPORT")
- && stricmp (Item, "SETNODES")
- && stricmp (Item, "DOOMVERSION")
- && stricmp (Item, "ADDSWITCHES")
- && stricmp (Item, "SETPLAYTYPE")
- && stricmp (Item, "SORTFILES")
- && stricmp (Item, "WADDIR"))
- {
- if (TotalAutoInc == MAXAUTOINCLUDE)
- Bye (RETURNERROR, "ERROR - Too many AUTOINCLUDE entries\n");
- if ((AutoInc[TotalAutoInc] = ((struct WadInfo_s far *)_fmalloc ((size_t)sizeof (struct WadInfo_s)))) == NOMEM)
- Bye (RETURNERROR, "FATAL ERROR - Out of memory\n");
- DriveChanged = FALSE;
- strcpy (S, TestName (Item));
- if (S[1] == ':') /* Preceded by drive: ? */
- {
- if (strlen (S) == 2) /* Just a drive, no path ? */
- Bye (RETURNERROR, "ERROR - Missing path for AUTOINCLUDE in configuration file\n");
- DriveNo = ToNumber (S[0]);
- if (DriveNo != CurDrive) /* A new drive ? */
- {
- _dos_setdrive (DriveNo, &Dummy);
- _dos_getdrive (&Dummy);
- DriveChanged = (Dummy == DriveNo); /* Check that the change has been made */
- AutoInc[TotalAutoInc]->Drive = DriveNo; /* Store drive number */
- }
- else
- AutoInc[TotalAutoInc]->Drive = 0; /* Signal: no new drive given */
- strcpy (AutoInc[TotalAutoInc]->Path, strupr (S + 2)); /* Store path */
- }
- else
- {
- AutoInc[TotalAutoInc]->Drive = 0; /* Signal: no drive given */
- strcpy (AutoInc[TotalAutoInc]->Path, strupr (S));
- }
- M = strlen (AutoInc[TotalAutoInc]->Path) - 1;
- while (AutoInc[TotalAutoInc]->Path[M] != '\\' && M > 0)
- M --;
- if (M == 0)
- {
- strcpy (AutoInc[TotalAutoInc]->OrigName, AutoInc[TotalAutoInc]->Path); /* No preceding path */
- strcpy (AutoInc[TotalAutoInc]->Path, DEFAULTWADDIR);
- }
- else
- {
- strcpy (AutoInc[TotalAutoInc]->OrigName, AutoInc[TotalAutoInc]->Path + M + 1); /* Copy over last part (filename) */
- AutoInc[TotalAutoInc]->Path[M] = '\0'; /* Cut filename from path */
- }
- if (DriveChanged)
- _dos_setdrive (CurDrive, &Dummy); /* Return to home drive */
- TotalAutoInc ++;
- NextString (Fp, Item); /* Read next argument */
- }
- }
- if (!stricmp (Item, "WADINFOFILE"))
- {
- InfoDefined = TRUE; /* Signal: InfoFile has been defined */
- NextString (Fp, Item);
- if (!strlen (Item))
- Bye (RETURNERROR, "ERROR - Invalid configuration file\n");
- strcpy (InfoFile, TestName (Item));
- NextString (Fp, Item); /* Read next keyword */
- }
- if (!stricmp (Item, "SETPLAYTYPE"))
- {
- NextString (Fp, Item);
- if (!strlen (Item))
- Bye (RETURNERROR, "ERROR - Missing playtype in configuration file\n");
- if (!stricmp (Item, "ALONE"))
- PlayTypeActive = 1;
- else
- if (!stricmp (Item, "IPX"))
- PlayTypeActive = 2;
- else
- if (!stricmp (Item, "NULL"))
- PlayTypeActive = 3;
- else
- Bye (RETURNERROR, "ERROR - Unknown playtype %s in configuration file\n", Item);
- NextString (Fp, Item); /* Read next keyword */
- }
- if (!stricmp (Item, "SETSKILL"))
- {
- NextString (Fp, Item);
- if (strlen (Item) != 1 || Item[0] < '1' || Item[0] > '5')
- Bye (RETURNERROR, "ERROR - Invalid skill %s in configuration file\n", Item);
- DifficultyActive = Item[0] - '0';
- NextString (Fp, Item);
- }
- if (!stricmp (Item, "SETCOMPORT"))
- {
- NextString (Fp, Item);
- if (strlen (Item) != 1 || Item[0] < '1' || Item[0] > '4')
- Bye (RETURNERROR, "ERROR - Invalid COM port %s in configuration file\n", Item);
- CommPortActive = Item[0] - '0';
- NextString (Fp, Item);
- }
- if (!stricmp (Item, "SETNODES"))
- {
- NextString (Fp, Item);
- if (strlen (Item) != 1 || Item[0] < '2' || Item[0] > '4')
- Bye (RETURNERROR, "ERROR - Invalid number of nodes %s in configuration file\n", Item);
- NumNodesActive = Item[0] - '0';
- NextString (Fp, Item);
- }
- if (!stricmp (Item, "DEATHMATCH"))
- {
- DeathmatchOn = TRUE;
- NextString (Fp, Item);
- }
- if (!stricmp (Item, "DOOMVERSION"))
- {
- NextString (Fp, Item);
- DoomVersion = 0;
- if (Item[0] != '1' || Item[1] != '.') /* Version number must be one of 1.x */
- Bye (RETURNERROR, "ERROR - Invalid DOOM version number %s in configuration file\n", Item);
- for (M = 2 ; M < strlen (Item) && isdigit (Item[M]) ; M ++)
- DoomVersion = DoomVersion * 10 + Item[M] - '0';
- if (Item[M] != '\0')
- Bye (RETURNERROR, "ERROR - Invalid DOOM version number %s in configuration file\n", Item);
- if (DoomVersion == 3 || (DoomVersion > 6 && DoomVersion != 666)) /* Filter out non-existing version numbers */
- Bye (RETURNERROR, "ERROR - DOOM version number %s (in configuration file) does not exist!\n", Item);
- DVerDefined = TRUE;
- NextString (Fp, Item);
- }
- if (!stricmp (Item, "NOSEARCH"))
- {
- DoNotSearch = TRUE;
- NextString (Fp, Item);
- }
- if (!stricmp (Item, "ADDSWITCHES"))
- {
- NextString (Fp, Item);
- while (!feof (Fp) && Item[0] == '-') /* Remember that all switches start with a '-' character */
- {
- M = 0;
- while (M < MAXADDSWITCHES && stricmp (Item, ExtCom[M].Command))
- M ++;
- if (M == MAXADDSWITCHES)
- Bye (RETURNERROR, "ERROR - Unrecognised ADDSWITCHES %s in configuration file\n", Item);
- ExtCom[M].InUse = TRUE;
- NextString (Fp, Item);
- }
- }
- if (!stricmp (Item, "SORTFILES"))
- {
- NextString (Fp, Item);
- if (feof (Fp))
- Bye (RETURNERROR, "ERROR - Missing sort criteria after keyword SORTFILES\n");
- SortWADFiles = TRUE;
- if (!stricmp (Item, "NAME") || !stricmp (Item, "INFO"))
- SortByName = !stricmp (Item, "NAME");
- else
- Bye (RETURNERROR, "ERROR - Unknown sort criteria %s after keyword SORTFILES\n", Item);
- NextString (Fp, Item);
- }
- if (!feof (Fp)
- && stricmp (Item, "WADINFOFILE")
- && stricmp (Item, "WADDIR")
- && stricmp (Item, "SETSKILL")
- && stricmp (Item, "DEATHMATCH")
- && stricmp (Item, "NOSEARCH")
- && stricmp (Item, "DOOMDIR")
- && stricmp (Item, "SETCOMPORT")
- && stricmp (Item, "SETNODES")
- && stricmp (Item, "SETPLAYTYPE")
- && stricmp (Item, "DOOMVERSION")
- && stricmp (Item, "ADDSWITCHES")
- && stricmp (Item, "SORTFILES")
- && stricmp (Item, "AUTOINCLUDE"))
- Bye (RETURNERROR, "ERROR - Unknown keyword %s in configuration file\n", Item);
- }
- }
- else
- if (ConfigChange) /* It is an error if a different file was given */
- Bye (RETURNERROR, "ERROR - configuration file not found\n");
- if (!DoomDefined) /* No CONFIGFILE or DOOMDIR defined ? */
- {
- strcpy (DoomDirectory, DEFAULTWADDIR); /* Then use the current directory as default */
- DoomDrive = 0;
- }
- if (!DirsDefined) /* No CONFIGFILE or WADDIR entries found ? */
- {
- if ((WadDir[0] = ((struct WadDir_s far *)_fmalloc ((size_t)sizeof (struct WadDir_s)))) == NOMEM)
- Bye (RETURNERROR, "FATAL ERROR - Out of memory\n");
- WadDir[0]->Drive = 0; /* Then use the DOOM directory as default */
- strcpy (WadDir[0]->Name, DoomDirectory);
- TotalWadDirs = 1;
- }
- if (!InfoDefined) /* No CONFIGFILE or WADINFOFILE defined ? */
- strcpy (InfoFile, DEFAULTINFOFILE); /* Then initialize a default file name */
- if (!DVerDefined) /* No CONFIGFILE or DOOMVERSION defined ? */
- DoomVersion = DEFAULTVERSION; /* Then initialize a default version number */
- for (M = 0 ; M < MAXADDSWITCHES ; M ++)
- if (ExtCom[M].InUse && ExtCom[M].VersionNeeded > DoomVersion)
- Bye (RETURNERROR, "ERROR - Switch %s needs DOOM version 1.%d\n", ExtCom[M].Command, ExtCom[M].VersionNeeded);
- if (DoomVersion < 2)
- {
- if (DeathmatchOn)
- Bye (RETURNERROR, "ERROR - Switch DEATHMATCH needs DOOM version 1.2\n");
- if (DifficultyActive == 5)
- Bye (RETURNERROR, "ERROR - Skill level 5 needs DOOM version 1.2\n");
- if (CommPortActive != DEFAULTCOMPORT)
- Bye (RETURNERROR, "ERROR - Switch SETCOMPORT needs DOOM version 1.2\n");
- if (PlayTypeActive == 3)
- Bye (RETURNERROR, "ERROR - Switch SETPLAYTYPE NULL needs DOOM version 1.2\n");
- if (PlayTypeActive == 2 && DoomVersion == 0)
- Bye (RETURNERROR, "ERROR - Switch SETPLAYTYPE IPX needs DOOM version 1.2\n");
- if (NumNodesActive != DEFAULTNODES && DoomVersion == 0)
- Bye (RETURNERROR, "ERROR - Switch SETNODES needs DOOM version 1.2\n");
- }
- }
-
- void PrintEpisodes (char HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' contains the pointed episode, or 0 if none was pointed to. */
- /* Post : The episodes have been printed. The active episode has a checked box, all others have empty boxes. The pointed episode */
- /* is printed in a different color. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- for (M = 0 ; M < NUMEPISODE ; M ++)
- {
- if (M == HighLite - 1)
- PrText ((M == EpisodeActive - 1), 3 + M, 1, LRED, Episodes[M]);
- else
- PrText ((M == EpisodeActive - 1), 3 + M, 1, LMAGENTA, Episodes[M]);
- }
- }
-
- void PrintDifficulties (char HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' contains the pointed difficulty, or 0 if none was pointed to. */
- /* Post : The difficulties have been printed. The active difficulty has a checked box, all others have empty boxes. The pointed */
- /* difficulty is printed in a different color. */
- /* If (global) 'DoomVersion' is less than 1.2, then the difficulty 'Nightmare' (the last in the row) is not printed. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- int MaxDiff;
-
- MaxDiff = (DoomVersion >= 2) ? NUMDIFFICULTY : NUMDIFFICULTY - 1;
- for (M = 0 ; M < MaxDiff ; M ++)
- {
- if (M == HighLite - 1)
- PrText ((M == DifficultyActive - 1), 3 + M, 28, LRED, Difficulties[M]);
- else
- PrText ((M == DifficultyActive - 1), 3 + M, 28, LMAGENTA, Difficulties[M]);
- }
- }
-
- void PrintPlayTypes (char HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' contains the pointed playtype, or 0 if none was pointed to. */
- /* Post : The playtypes have been printed. The active playtype has a checked box, all others have empty boxes. The pointed */
- /* playtype is printed in a different color. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (DoomVersion == 0) /* Doom v1.0 could only be played alone */
- return;
- for (M = 0 ; M < ((DoomVersion >= 2) ? NUMPLAYTYPE : NUMPLAYTYPE - 1) ; M ++) /* v1.1 had IPX, v1.2 also had modem */
- {
- if (M == HighLite - 1)
- PrText ((M == PlayTypeActive - 1), 3 + M, 56, LRED, PlayTypes[M]);
- else
- PrText ((M == PlayTypeActive - 1), 3 + M, 56, LMAGENTA, PlayTypes[M]);
- }
- switch (PlayTypeActive)
- {
- case 1: PrText (-1, 6, 56, DBLACK, " "); /* Alone */
- break;
- case 2: if (HighLite == 4) /* IPX compatible */
- PrText (-1, 6, 56, LRED, "[%c] %s", NumNodesActive + '0', NumberNodes);
- else
- PrText (-1, 6, 56, LMAGENTA, "[%c] %s", NumNodesActive + '0', NumberNodes);
- break;
- case 3: if (HighLite == 4) /* Null-modem link */
- PrText (-1, 6, 56, LRED, "[%c] %s", CommPortActive + '0', CommPort);
- else
- PrText (-1, 6, 56, LMAGENTA, "[%c] %s", CommPortActive + '0', CommPort);
- }
- }
-
- void PrintDeathmatch (boolean HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' is TRUE if this item was pointed to. */
- /* Post : The DEATHMATCH text has been printed, with a checked box before it if it was selected, or empty otherwise. */
- /* If 'HighLite' was TRUE, then the text is printed in a different color. */
- /* If (global) 'DoomVersion' is less than 1.2, then nothing has been done here. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (DoomVersion >= 2)
- if (HighLite)
- PrText (DeathmatchOn, 7, 56, LRED, Deathmatch);
- else
- PrText (DeathmatchOn, 7, 56, LMAGENTA, Deathmatch);
- }
-
- void PrintLevel (boolean HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' is TRUE if this item was pointed to. */
- /* Post : The LEVEL text has been printed, with a box before it, containing the current level. */
- /* If 'HighLite' was TRUE, then the text is printed in a different color. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (HighLite)
- PrText (-1, 7, 1, LRED, "[%c] %s", CurrentLevel + '0', Level);
- else
- PrText (-1, 7, 1, LMAGENTA, "[%c] %s", CurrentLevel + '0', Level);
- }
-
- void PrintWadFiles (void)
-
- /**********************************************************************************************************************************/
- /* Pre : None. */
- /* Post : The active page with WAD files has been printed (as determined by 'CurrentPage') has been printed. All selected WAD */
- /* files are printed in a different color, any unused part of the page has been cleared from the screen. After each name */
- /* is the read info printed. Highliting of a pointed wadfile is not handled here. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- int PositionX;
- int PositionY;
-
- for (M = CurrentPage * PAGE ; M < (CurrentPage + 1) * PAGE ; M += WADHEIGHT) /* Handle each column */
- for (N = M ; N < M + WADHEIGHT ; N ++) /* Handle each row in the column */
- {
- PositionY = 11 + (N % WADHEIGHT);
- PositionX = ((M - CurrentPage * PAGE) / WADHEIGHT) * WADWIDTH + 1;
- if (N < TotalWads) /* WAD file number exists ? */
- {
- if (WadInfo[N]->Selected)
- PrText (-1, PositionY, PositionX, DGREEN, WadInfo[N]->Name); /* Print filename */
- else
- PrText (-1, PositionY, PositionX, DWHITE, WadInfo[N]->Name);
- PrText (-1, PositionY, PositionX + _MAX_FNAME, DCYAN, WadInfo[N]->Info); /* Print info */
- }
- else /* WAD file number after the last WAD file */
- PrText (-1, PositionY, PositionX, DBLACK, " "); /* Clear this screen part */
- }
- }
-
- void PrintPagers (char HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' is 1 for left, 2 for right or 0 for no pager. */
- /* Post : The pagers have been printed. The 'HighLite' pager in a different color. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (HighLite == 1) /* Print pager for 'previous' page (left) */
- PrText (-1, 9, 69, LRED, PreviousPage);
- else
- PrText (-1, 9, 69, LWHITE, PreviousPage);
- if (HighLite == 2) /* Print pager for 'next' page (right) */
- PrText (-1, 9, 78, LRED, NextPage);
- else
- PrText (-1, 9, 78, LWHITE, NextPage);
- }
-
- void PrintRdPrev (boolean HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' is TRUE if this item is selected. */
- /* Post : The read previous text has been printed. If 'HighLite' was TRUE, than in a different color. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (HighLite)
- PrText (-1, 9, 40, LRED, ReadPrevious);
- else
- PrText (-1, 9, 40, LWHITE, ReadPrevious);
- }
-
- void PrintAutomatic (boolean HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' is TRUE if this item is selected. */
- /* Post : The automatic text has been printed. If 'HighLite' was TRUE, than in a different color. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (HighLite)
- PrText (-1, 9, 20, LRED, Automatic);
- else
- PrText (-1, 9, 20, LWHITE, Automatic);
- }
-
- void PrintStart (boolean HighLite)
-
- /**********************************************************************************************************************************/
- /* Pre : 'HighLite' is TRUE if this item is selected. */
- /* Post : The start text has been printed. If 'HighLite' was TRUE, than in a different color. */
- /* Import: None. */
- /**********************************************************************************************************************************/
-
- {
- if (HighLite)
- PrText (-1, 9, 1, LRED, StartGame);
- else
- PrText (-1, 9, 1, LWHITE, StartGame);
- }
-
- void UnselectPreviousField (char SkipFieldNum)
-
- /**********************************************************************************************************************************/
- /* Pre : 'SkipFieldNum' holds the field number that should NOT be unselected. */
- /* Post : The previous selected field has been unselected, if one was pointed to and it was not 'SkipFieldNum'. */
- /* Import: PrintEpisodes, PrintDifficulties, PrintPlayTypes, PrintLevel, PrintDeathmatch, PrintPagers, PrintRdPrev, PrintStart, */
- /* PrintAutomatic. */
- /**********************************************************************************************************************************/
-
- {
- if (CurrentField != NOFIELD && CurrentField != SkipFieldNum)
- {
- switch (CurrentField)
- {
- case EPISODEFIELD : PrintEpisodes (0);
- break;
- case DIFFICULTYFIELD : PrintDifficulties (0);
- break;
- case PLAYTYPEFIELD : PrintPlayTypes (0);
- break;
- case LEVELFIELD : PrintLevel (FALSE);
- break;
- case DEATHMATCHFIELD : PrintDeathmatch (FALSE);
- break;
- case PAGERFIELD : PrintPagers (0);
- break;
- case RDPREVFIELD : PrintRdPrev (FALSE);
- break;
- case STARTFIELD : PrintStart (FALSE);
- break;
- case AUTOMATICFIELD : PrintAutomatic (FALSE);
- }
- }
- }
-
- void HandleFile (unsigned int Key)
-
- /**********************************************************************************************************************************/
- /* Pre : 'Key' holds the preesed (raw) key code that caused calling this routine; if (global) 'UseMouse' was FALSE. */
- /* Considered keys are the cursor keys and space. If 'UseMouse' was TRUE, than 'Key' is always 0x0000 (dummy). */
- /* Post : The mouse pointer was at the bottom of the screen. The pointed filename has been highlighted. If the right mousebutton */
- /* was pressed, then the file is selected, which is shown by a different color. If the file was already selected, then it */
- /* is now deselected. Selection can only be done once on a button press. To invert the selection, the mouse button must */
- /* first be released, and then pressed again. */
- /* Import: HideMouse, ShowMouse, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- int PositionX;
- int PositionY;
- int OldWadNumber;
- int NewWadNumber;
-
- UnselectPreviousField (FILEFIELD);
- PositionY = 11 + ((PreviousWad - 1) % WADHEIGHT); /* Location of previously selected WAD */
- PositionX = ((PreviousWad - 1) / WADHEIGHT) * WADWIDTH + 1;
- OldWadNumber = CurrentPage * PAGE + PreviousWad - 1; /* Number of that WAD */
- if (UseMouse && Mouse.Yy == 9) /* One line above the first files */
- {
- if (CurrentField == FILEFIELD && Mouse.CoChange) /* Only necessary if going up */
- {
- HideMouse ();
- if (WadInfo[OldWadNumber]->Selected)
- PrText (-1, PositionY, PositionX, DGREEN, WadInfo[OldWadNumber]->Name);
- else
- PrText (-1, PositionY, PositionX, DWHITE, WadInfo[OldWadNumber]->Name);
- ShowMouse ();
- CurrentField = NOFIELD;
- }
- }
- else
- {
- CurrentSelected = 0; /* Signal: no file pointed to */
- if (UseMouse)
- {
- if (Mouse.Xx <= 7) /* Determine the file column */
- CurrentSelected = Mouse.Yy - 9;
- else
- if (Mouse.Xx >= 27 && Mouse.Xx <= 34)
- CurrentSelected = Mouse.Yy - 9 + WADHEIGHT;
- else
- if (Mouse.Xx >= 54 && Mouse.Xx <= 61)
- CurrentSelected = Mouse.Yy - 9 + (2 * WADHEIGHT);
- if (CurrentPage * PAGE + CurrentSelected > TotalWads) /* Empty screen part */
- CurrentSelected = -1;
- MouseHidden = FALSE;
- if (CurrentField == FILEFIELD && Mouse.CoChange) /* Only unhighlite the previous one if the mouse moved */
- {
- HideMouse ();
- MouseHidden = TRUE; /* Signal: mouse pointer hidden */
- if (WadInfo[OldWadNumber]->Selected)
- PrText (-1, PositionY, PositionX, DGREEN, WadInfo[OldWadNumber]->Name);
- else
- PrText (-1, PositionY, PositionX, DWHITE, WadInfo[OldWadNumber]->Name);
- }
- }
- else
- {
- switch (Key)
- {
- case KEY_CURSLEFT : if (PreviousWad > WADHEIGHT) /* Possible to go left ? */
- CurrentSelected = PreviousWad - WADHEIGHT;
- else /* Determine the far right and go there */
- if ((CurrentPage * PAGE + PreviousWad + 2 * WADHEIGHT) <= TotalWads)
- CurrentSelected = PreviousWad + 2 * WADHEIGHT; /* 3 columns */
- else
- if ((CurrentPage * PAGE + PreviousWad + WADHEIGHT) <= TotalWads) /* 2 columns */
- CurrentSelected = PreviousWad + WADHEIGHT;
- else /* Only 1 column; no move possible */
- CurrentSelected = PreviousWad;
- break;
- case KEY_CURSRIGHT : if ((PreviousWad < 2 * WADHEIGHT) && (CurrentPage * PAGE + PreviousWad + WADHEIGHT) <= TotalWads)
- CurrentSelected = PreviousWad + WADHEIGHT;
- else
- CurrentSelected = PreviousWad % WADHEIGHT;
- break;
- case KEY_CURSUP : if (((PreviousWad - 1) % WADHEIGHT) > 0)
- CurrentSelected = PreviousWad - 1;
- else
- if ((CurrentPage * PAGE + PreviousWad + WADHEIGHT) <= TotalWads)
- CurrentSelected = PreviousWad - 1 + WADHEIGHT;
- else
- CurrentSelected = TotalWads % PAGE;
- break;
- case KEY_CURSDOWN : if (((PreviousWad - 1) % WADHEIGHT) < (WADHEIGHT - 1))
- if ((CurrentPage * PAGE + PreviousWad + 1) <= TotalWads)
- CurrentSelected = PreviousWad + 1;
- else
- CurrentSelected = (TotalWads % PAGE) - (TotalWads % WADHEIGHT) + 1;
- else
- CurrentSelected = PreviousWad + 1 - WADHEIGHT;
- break;
- case KEY_SELECTFILE : CurrentSelected = PreviousWad;
- }
- if (Key != KEY_SELECTFILE) /* Unhighlite the previous one */
- if (WadInfo[OldWadNumber]->Selected)
- PrText (-1, PositionY, PositionX, DGREEN, WadInfo[OldWadNumber]->Name);
- else
- PrText (-1, PositionY, PositionX, DWHITE, WadInfo[OldWadNumber]->Name);
- }
- NewWadNumber = CurrentPage * PAGE + CurrentSelected - 1;
- if ((UseMouse && (Mouse.Left && !Mouse.LeftStillPressed && CurrentSelected > 0)) /* Mouse button pressed ? */
- || (Key == KEY_SELECTFILE))
- {
- WadInfo[NewWadNumber]->Selected = !WadInfo[NewWadNumber]->Selected; /* Invert selection */
- SelectionChange = TRUE; /* Signal: screenchange */
- }
- else
- SelectionChange = FALSE;
- if (CurrentSelected > 0) /* A (valid) new file is pointed to */
- {
- if (Mouse.CoChange || SelectionChange || !UseMouse) /* Color change needed ? */
- {
- PositionY = 11 + ((CurrentSelected - 1) % WADHEIGHT);
- PositionX = ((CurrentSelected - 1) / WADHEIGHT) * WADWIDTH + 1;
- if (!MouseHidden) /* Hide the mouse if not hidden already */
- HideMouse ();
- MouseHidden = TRUE;
- if (WadInfo[NewWadNumber]->Selected) /* 'Draw' highlite bar */
- PrText (-1, PositionY, PositionX, LGREEN, WadInfo[NewWadNumber]->Name);
- else
- PrText (-1, PositionY, PositionX, LRED, WadInfo[NewWadNumber]->Name);
- }
- CurrentField = FILEFIELD;
- PreviousWad = CurrentSelected;
- }
- else
- CurrentField = NOFIELD;
- if (MouseHidden) /* Reprint the mouse pointer if needed */
- ShowMouse ();
- }
- }
-
- void HandleEpisode (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because of a keypress. */
- /* Post : The mouse pointer was at the episode block. The pointed episode has been highlited. If the mouse button was pressed, */
- /* then this episode is selected (and the previous automatically de-selected). The new result is reprinted. */
- /* Import: HideMouse, ShowMouse, PrintEpisodes, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- HideMouse ();
- UnselectPreviousField (EPISODEFIELD);
- if (Mouse.Left && !Mouse.LeftStillPressed) /* Mouse button pressed ? */
- EpisodeActive = Mouse.Yy - 1; /* Make the highlited episode active */
- else
- if (KeyInput) /* Key pressed */
- if (++ EpisodeActive > NUMEPISODE) /* Increase episode number */
- EpisodeActive = 1;
- if (KeyInput)
- if (CurrentField == EPISODEFIELD)
- PrintEpisodes (Mouse.Yy - 1);
- else
- PrintEpisodes (0);
- else
- {
- PrintEpisodes (Mouse.Yy - 1);
- CurrentField = EPISODEFIELD;
- }
- ShowMouse ();
- }
-
- void HandleDifficulty (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because of a keypress. */
- /* Post : The mouse pointer was at the difficulty block. The pointed difficulty has been highlited. If the mouse button was */
- /* pressed then this difficulty is selected (and the previous automatically de-selected). The new result is reprinted. */
- /* Import: HideMouse, ShowMouse, PrintDifficulties, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- int MaxDiff;
-
- MaxDiff = (DoomVersion >= 2) ? NUMDIFFICULTY : NUMDIFFICULTY - 1;
- HideMouse ();
- UnselectPreviousField (DIFFICULTYFIELD);
- if (Mouse.Left && !Mouse.LeftStillPressed)
- DifficultyActive = Mouse.Yy - 1;
- else
- if (KeyInput)
- if (++ DifficultyActive > MaxDiff)
- DifficultyActive = 1;
- if (KeyInput)
- if (CurrentField == DIFFICULTYFIELD)
- PrintDifficulties (Mouse.Yy - 1);
- else
- PrintDifficulties (0);
- else
- {
- PrintDifficulties (Mouse.Yy - 1);
- CurrentField = DIFFICULTYFIELD;
- }
- ShowMouse ();
- }
-
- void HandlePlayType (boolean KeyInput, char Key)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because of a keypress. */
- /* If it was TRUE, then 'Key' holds the (ASCII) keyvalue, otherwise 'Key' holds 0x00 (dummy). */
- /* Post : The mouse pointer was at the playtype block. The pointed playtype has been highlited. If the mouse button was pressed */
- /* then this playtype is selected (and the previous automatically de-selected). The new result is reprinted. */
- /* If the mouse pointer was at the fourth line, than the PlayType parameter of the current PlayType is handled. */
- /* Import: HideMouse, ShowMouse, PrintPlayTypes, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- int Mpt;
-
- if (DoomVersion == 0)
- return;
- HideMouse ();
- Mpt = ((DoomVersion >= 2) ? NUMPLAYTYPE : NUMPLAYTYPE - 1);
- UnselectPreviousField (PLAYTYPEFIELD);
- if (KeyInput)
- {
- switch (Key)
- {
- case KEY_PLAYTYPE : if (++ PlayTypeActive > Mpt)
- PlayTypeActive = 1;
- break;
- case KEY_NODES : if (PlayTypeActive == 2) /* IPX compatible */
- if (++ NumNodesActive == 5) /* Increase number of players */
- NumNodesActive = 2; /* Must be between 2 and 4 */
- break;
- case KEY_COMPORT : if (PlayTypeActive == 3) /* Null-modem link */
- if (++ CommPortActive == 5) /* Increase COM port number */
- CommPortActive = 1; /* Must be between 1 and 4 */
- }
- if (CurrentField == PLAYTYPEFIELD)
- PrintPlayTypes (Mouse.Yy - 1);
- else
- PrintPlayTypes (0);
- }
- else /* Mouse input */
- {
- if (Mouse.Left && !Mouse.LeftStillPressed)
- if (Mouse.Yy <= Mpt + 1) /* Change PlayType ? */
- PlayTypeActive = Mouse.Yy - 1;
- else
- if (PlayTypeActive == 2) /* IPX compatible */
- {
- if (++ NumNodesActive == 5) /* Increase number of players */
- NumNodesActive = 2; /* Must be between 2 and 4 */
- }
- else
- if (PlayTypeActive == 3) /* Null-modem link */
- {
- if (++ CommPortActive == 5) /* Increase COM port number */
- CommPortActive = 1; /* Must be between 1 and 4 */
- }
- PrintPlayTypes (Mouse.Yy - 1);
- CurrentField = PLAYTYPEFIELD;
- }
- ShowMouse ();
- }
-
- void HandleDeathmatch (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because of a keypress. */
- /* Post : The mouse pointer was at the deathmatch item. This item has been highlited. If the mouse button was pressed, then the */
- /* active value is inverted. The new result is reprinted. */
- /* If (global) 'DoomVersion' is less than 1.2, then nothing has been done here. */
- /* Import: HideMouse, ShowMouse, PrintDeathmatch, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- if (DoomVersion >= 2)
- {
- UnselectPreviousField (DEATHMATCHFIELD);
- if ((Mouse.Left && !Mouse.LeftStillPressed) || KeyInput)
- DeathmatchOn = !DeathmatchOn; /* Toggle the DEATHMATCH item */
- HideMouse ();
- if (KeyInput)
- PrintDeathmatch (CurrentField == DEATHMATCHFIELD);
- else
- {
- PrintDeathmatch (TRUE);
- CurrentField = DEATHMATCHFIELD;
- }
- ShowMouse ();
- }
- }
-
- void HandleLevel (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because of a keypress. */
- /* Post : The mouse pointer was at the level item. This level has been highlited. If the mouse button was pressed, then the */
- /* active level is increased. If it exceeded 9, then it is wrapped back to 1. The new result is reprinted. */
- /* Import: HideMouse, ShowMouse, PrintLevel, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- UnselectPreviousField (LEVELFIELD);
- if ((Mouse.Left && !Mouse.LeftStillPressed) || KeyInput)
- if (++ CurrentLevel > NUMLEVEL) /* Increase current level */
- CurrentLevel = 1; /* After level 9 comes level 1 again */
- HideMouse ();
- if (KeyInput)
- PrintLevel (CurrentField == LEVELFIELD);
- else
- {
- CurrentField = LEVELFIELD;
- PrintLevel (TRUE);
- }
- ShowMouse ();
- }
-
- void HandlePreviousPage (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine is entered because the [PAGE UP] key was pressed. */
- /* Post : The mouse pointer was at the previouspage item. This item has been highlited. If the mouse button was pressed, then */
- /* a test is made if there are previous pages. If not, then the keyboard bell is sound, otherwise the previous page has */
- /* been made the current. This new page has been printed. */
- /* Import: HideMouse, ShowMouse, PrintWadFiles, PrintPagers, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- HideMouse ();
- UnselectPreviousField (PAGERFIELD);
- if ((Mouse.Left && !Mouse.LeftStillPressed) || KeyInput)
- if (CurrentPage == 0) /* Report the error if already at page 0 */
- printf ("%c", 0x07);
- else
- {
- CurrentPage --; /* Go back a page */
- PrintWadFiles (); /* Print this new page */
- if (!UseMouse)
- PrText (-1, 11 + ((PreviousWad - 1) % WADHEIGHT),
- ((PreviousWad - 1) / WADHEIGHT) * WADWIDTH + 1,
- LRED, WadInfo[CurrentPage * PAGE + PreviousWad - 1]->Name); /* Hi-light 'new current' WAD file */
- }
- if (!KeyInput)
- {
- PrintPagers (1);
- CurrentField = PAGERFIELD;
- }
- ShowMouse ();
- }
-
- void HandleNextPage (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because the user pressed the [PAGE DOWN] key. */
- /* Post : The mouse pointer was at the nextpage item. This item has been highlited. If the mouse button was pressed, then a test */
- /* is made if there are next pages. If not, then the keyboard bell is sound, otherwise the next page has been made the */
- /* current. This new page has been printed. */
- /* Import: HideMouse, ShowMouse, PrintWadFiles, PrintPagers, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- HideMouse ();
- UnselectPreviousField (PAGERFIELD);
- if ((Mouse.Left && !Mouse.LeftStillPressed) || KeyInput)
- if (CurrentPage == (TotalWads / PAGE)) /* Report the error if already at the last page */
- printf ("%c", 0x07);
- else
- {
- CurrentPage ++;
- PrintWadFiles ();
- if (!UseMouse)
- {
- if ((CurrentPage * PAGE + PreviousWad - 1) > TotalWads) /* If not a full page, then test that the new pointed */
- PreviousWad = TotalWads % PAGE; /* WAD file is valid, otherwise set it to the last one */
- PrText (-1, 11 + ((PreviousWad - 1) % WADHEIGHT),
- ((PreviousWad - 1) / WADHEIGHT) * WADWIDTH + 1,
- LRED, WadInfo[CurrentPage * PAGE + PreviousWad - 1]->Name); /* Hi-light 'new current' WAD file */
- }
- }
- if (!KeyInput)
- {
- PrintPagers (2);
- CurrentField = PAGERFIELD;
- }
- ShowMouse ();
- }
-
- void HandleReadPrev (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because of a keypress. */
- /* Post : The mouse pointer was at the read previous item. This item has been highlited. If the mouse button was pressed, then */
- /* the file 'START.BAT' is read. Each item is set to the read value, all read WAD files are selected. */
- /* Import: HideMouse, ShowMouse, PrintRdPrev, PrintEpisodes, PrintDifficulties, PrintPlayTypes, PrintDeathmatch, PrintLevel, */
- /* PrintWadFiles, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- FILE *Fp;
- char FileName[_MAX_FNAME];
- char Directory[_MAX_DIR];
- char Tmp[_MAX_DIR];
- char DriveNum;
- boolean Handled;
- boolean Stop;
-
- HideMouse ();
- UnselectPreviousField (RDPREVFIELD);
- if (!KeyInput)
- {
- PrintRdPrev (TRUE);
- CurrentField = RDPREVFIELD;
- }
- if ((Mouse.Left && !Mouse.LeftStillPressed) || KeyInput)
- {
- Stop = FALSE;
- if (!(Fp = fopen (BATFILE, "r"))) /* Open "START.BAT" */
- Stop = TRUE;
- else
- {
- EpisodeActive = DEFAULTEPISODE; /* Set all items to their defaults */
- DifficultyActive = DEFAULTDIFFICULTY;
- PlayTypeActive = DEFAULTPLAYTYPE;
- CurrentLevel = DEFAULTLEVEL;
- DeathmatchOn = FALSE;
- CommPortActive = DEFAULTCOMPORT;
- NumNodesActive = DEFAULTNODES;
- for (M = 0 ; M < TotalWads ; M ++) /* Unselect all WAD files */
- WadInfo[M]->Selected = FALSE;
- fscanf (Fp, "%s", S); /* First read the command */
- while (!feof (Fp)
- && stricmp (S, STARTALONE)
- && stricmp (S, STARTIPX)
- && stricmp (S, STARTLINK))
- fscanf (Fp, "%s", S);
- if (!stricmp (S, STARTALONE))
- PlayTypeActive = 1;
- else
- if (!stricmp (S, STARTIPX))
- PlayTypeActive = 2;
- else
- if (!stricmp (S, STARTLINK))
- PlayTypeActive = 3;
- else
- Stop = TRUE; /* Not a DOOM start command */
- if (!Stop)
- {
- fscanf (Fp, "%s", S);
- while (!feof (Fp) && !Stop) /* Handle each parameter */
- {
- Handled = FALSE;
- if (S[0] == '@') /* 'Response' file following */
- {
- fclose (Fp); /* Close "START.BAT" */
- if (!(Fp = fopen (S + 1, "r"))) /* Open the 'Response' file */
- Stop = TRUE; /* Stop if the file does not exist */
- else
- fscanf (Fp, "%s", S); /* Else: read the first string */
- }
- if (!feof (Fp) && !stricmp (S, SKILL) && !Stop) /* Found '-SKILL' */
- {
- fscanf (Fp, "%s", S); /* '-SKILL' takes a parameter: 1-5 */
- if (feof (Fp) || strlen (S) != 1 || S[0] <= LO_DIFF || S[0] > HI_DIFF)
- Stop = TRUE;
- else
- {
- DifficultyActive = S[0] - LO_DIFF;
- Handled = TRUE;
- fscanf (Fp, "%s", S);
- }
- }
- if (!feof (Fp) && !stricmp (S, DMATCH) && !Stop) /* Found '-DEATHMATCH' */
- {
- DeathmatchOn = TRUE;
- Handled = TRUE;
- fscanf (Fp, "%s", S);
- }
- if (!feof (Fp) && !stricmp (S, DEVPARM) && !Stop) /* Found '-DEVPARM' */
- {
- Handled = TRUE; /* (Ignore the keyword) */
- fscanf (Fp, "%s", S);
- }
- if (!feof (Fp) && !stricmp (S, GOTOANYTHING) && !Stop) /* Found '-WART' */
- {
- fscanf (Fp, "%s", S); /* '-WART' takes two parameters: episode (1-3) and level (1-9) */
- if (feof (Fp) || strlen (S) != 1 || S[0] <= LO_EPIS || S[0] > HI_EPIS)
- Stop = TRUE;
- else
- {
- EpisodeActive = S[0] - LO_EPIS;
- fscanf (Fp, "%s", S);
- if (feof (Fp) || strlen (S) != 1 || S[0] <= LO_LEVL || S[0] > HI_LEVL)
- Stop = TRUE;
- else
- {
- CurrentLevel = S[0] - LO_LEVL;
- Handled = TRUE;
- fscanf (Fp, "%s", S);
- }
- }
- }
- if (!feof (Fp) && !strnicmp (S, COMPORT, 4) && !Stop) /* Found '-COM#' */
- {
- if (strlen (S) != 5 || S[4] <= LO_COMM || S[0] > HI_COMM) /* COM port number is last char in this string */
- Stop = TRUE; /* Port number must be between 1-4 */
- else
- {
- CommPortActive = S[4] - LO_COMM;
- Handled = TRUE;
- fscanf (Fp, "%s", S);
- }
- }
- if (!feof (Fp) && !stricmp (S, NUMPLAYERS) && !Stop) /* Found '-NODES' */
- {
- fscanf (Fp, "%s", S); /* '-NODES' takes a parameter: 2-4 */
- if (feof (Fp) || strlen (S) != 1 || S[0] <= LO_NODE || S[0] > HI_NODE)
- Stop = TRUE;
- else
- {
- NumNodesActive = S[0] - '0';
- Handled = TRUE;
- fscanf (Fp, "%s", S);
- }
- }
- if (!feof (Fp) && !stricmp (S, GOTOEPISODE) && !Stop) /* Found '-EPISODE' */
- {
- fscanf (Fp, "%s", S); /* '-EPISODE' takes a parameter: 1-3 */
- if (feof (Fp) || strlen (S) != 1 || S[0] <= LO_EPIS || S[0] > HI_EPIS)
- Stop = TRUE;
- else
- {
- EpisodeActive = S[0] - LO_EPIS;
- Handled = TRUE;
- fscanf (Fp, "%s", S);
- }
- }
- if (!feof (Fp) && !stricmp (S, INCFILE) && !Stop) /* Found '-FILE' */
- {
- fscanf (Fp, "%s", S); /* Read-ahead first filename (at least 1 needed) */
- do /* Each following word is a filename, until the */
- { /* next keyword is found or EOF is encountered */
- if (!feof (Fp) && !Stop)
- {
- DriveNum = DoomDrive; /* Assume: not preceded by a drive: */
- if (S[1] == ':') /* Preceded by drive: */
- if (toupper (S[0]) < 'A' || toupper (S[0]) > 'Z')
- Stop = TRUE;
- else
- {
- DriveNum = ToNumber (S[0]);
- for (M = 2 ; M <= strlen (S) ; M ++) /* Cut drive */
- S[M - 2] = S[M];
- }
- if (!Stop)
- if (stricmp (S + strlen (S) - 4, ".WAD")) /* Filename MUST end with '.WAD' */
- Stop = TRUE;
- if (!Stop)
- {
- S[strlen (S) - 4] = '\0'; /* Cut the '.WAD' from the filename */
- M = strlen (S);
- if (!M || S[M - 1] == '\\') /* Ended with a '\' or no filename at all */
- Stop = TRUE;
- else
- {
- while (S[-- M] != '\\' && M >= 0)
- ;
- if (M >= 0) /* Preceded by path */
- {
- if (M == 0)
- strcpy (Directory, "\\"); /* Handle root differently */
- else
- {
- strncpy (Directory, strupr (S), M);
- Directory[M] = '\0';
- if (DriveNum == DoomDrive && Directory[0] != '\\')
- {
- sprintf (Tmp, "%s\\%s", DoomDirectory, Directory);
- strcpy (Directory, Tmp);
- }
- }
- strcpy (FileName, strupr (S) + M + 1);
- }
- else /* No path */
- {
- strcpy (FileName, strupr (S));
- if (DriveNum == DoomDrive)
- strcpy (Directory, DoomDirectory);
- else
- strcpy (Directory, DEFAULTWADDIR);
- }
- if (strlen (FileName) > 8) /* Filename contains more than 8 characters */
- Stop = TRUE;
- else
- {
- for (M = strlen (FileName) ; M < 8 ; M ++) /* Fill out filename to 8 characters */
- FileName[M] = ' ';
- FileName[M] = '\0';
- Handled = FALSE;
- for (M = 0 ; M < TotalWads && !Handled; M ++) /* Match against all WAD filenames in memory */
- if (WadInfo[M]->Drive == DriveNum)
- if (!strcmp (WadInfo[M]->Path, Directory))
- if (!strcmp (WadInfo[M]->Name, FileName))
- {
- Handled = TRUE;
- WadInfo[M]->Selected = TRUE; /* If it matches, than auto-select the file */
- }
- fscanf (Fp, "%s", S); /* Read next */
- }
- }
- }
- }
- }
- while (!feof (Fp) && S[0] != '-' && !Stop);
- Handled = TRUE;
- }
- if (!Handled && !feof (Fp) && !Stop)
- fscanf (Fp, "%s", S); /* Other switch: skip */
- }
- }
- fclose (Fp);
- PrintEpisodes (0); /* Redraw the screen with the read items */
- PrintLevel (FALSE);
- PrintDifficulties (0);
- PrintPlayTypes (0);
- PrintDeathmatch (FALSE);
- PrintWadFiles ();
- }
- }
- if (DoomVersion < 2) /* Reset all functions that have been read, but are for a higher version */
- {
- DeathmatchOn = FALSE;
- CommPortActive = DEFAULTCOMPORT;
- if (DifficultyActive == 5)
- DifficultyActive = DEFAULTDIFFICULTY;
- if (PlayTypeActive == 3 && DoomVersion < 2)
- PlayTypeActive = DEFAULTPLAYTYPE;
- if (PlayTypeActive == 2 && DoomVersion < 1)
- PlayTypeActive = DEFAULTPLAYTYPE;
- }
- ShowMouse ();
- }
-
- void HandleAutomatic (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because of a keypress. */
- /* Post : The mouse pointer was at the automatic item. This item has been highlited. If the mouse button was pressed, then this */
- /* routine reads all selected WAD files and initializes the current episode and level to the lowest ones found. */
- /* Import: HideMouse, ShowMouse, PrintAutomatic, PrintEpisodes, PrintLevel, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- long Startpoint;
- long LevelMask;
-
- UnselectPreviousField (AUTOMATICFIELD);
- if (!KeyInput)
- {
- HideMouse ();
- PrintAutomatic (TRUE);
- CurrentField = AUTOMATICFIELD;
- ShowMouse ();
- }
- if ((Mouse.Left && !Mouse.LeftStillPressed) || KeyInput)
- {
- Startpoint = 0x00000000;
- for (M = 0 ; M < TotalWads ; M ++)
- if (WadInfo[M]->Selected) /* Now merge all level information of all selcted WAD files */
- {
- GetWadInfo (M, TRUE);
- Startpoint |= WadInfo[M]->NewLevels;
- }
- if (Startpoint != 0x00000000)
- {
- CurrentLevel = 0;
- EpisodeActive = 1;
- LevelMask = 0x00000001;
- while ((Startpoint & LevelMask) != LevelMask) /* Search for the lowest episode and level */
- {
- LevelMask *= 2; /* Shift left */
- if (++ CurrentLevel == NUMLEVEL)
- {
- CurrentLevel = 0;
- EpisodeActive ++;
- }
- }
- if (++ CurrentLevel == NUMLEVEL)
- {
- CurrentLevel = 1;
- EpisodeActive ++;
- }
- }
- else
- {
- CurrentLevel = 1;
- EpisodeActive = 1;
- }
- PrintEpisodes (0); /* Redraw the screen with the new results */
- PrintLevel (0);
- }
- }
-
- boolean HandleStartGame (boolean KeyInput)
-
- /**********************************************************************************************************************************/
- /* Pre : 'KeyInput' is TRUE if this routine was called because of a keypress. */
- /* Post : The mouse pointer was at the startgame item. This item has been highlited. If the mouse button was pressed, then this */
- /* routine returns FALSE (which effectively means: start the game), otherwise TRUE. */
- /* Import: HideMouse, ShowMouse, PrintStart, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- UnselectPreviousField (STARTFIELD);
- if (!KeyInput)
- {
- HideMouse ();
- PrintStart (TRUE);
- CurrentField = STARTFIELD;
- ShowMouse ();
- }
- return ((!Mouse.Left || Mouse.LeftStillPressed) && !KeyInput);
- }
-
- int main (int argc, char *argv[])
-
- /**********************************************************************************************************************************/
- /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MAIN ROUTINE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
- /* Import: ResetMouse, ReadConfig, PrintEpisodes, PrintDifficulties, PrintPlayTypes, PrintDeathmatch, PrintLevel, PrintWadFiles, */
- /* PrintPagers, ShowMouse, MouseStatus, HandleEpisode, HandleDifficulty, HandleDeathmatch, HandleLevel, HandleNextPage, */
- /* HandlePreviousPage, HideMouse, DeAllocateAll, PrintStart, PrintRdPrev, HandleStartGame, HandleReadPrev, GetWadInfo, */
- /* WriteWadInfo, PrintAutomatic, HandleAutomatic, HandlePlayType, UnselectPreviousField. */
- /**********************************************************************************************************************************/
-
- {
- FILE *Fp;
- struct find_t FileBlock;
- struct WadInfo_s ReadInfo; /* Entry as read from the WADINFOFILE */
- struct WadInfo_s far *TmpPtr; /* Entry as read from the WADINFOFILE */
- char DrivePath[_MAX_DIR]; /* Current directory of a drive */
- char NextArgument; /* Argument number on the command line */
- char Ch;
- char SepChar; /* Seperation char in START.*; '\n' or ' ' */
- boolean SepCharNeeded;
- boolean More;
- boolean FirstWad; /* First WAD file to include in START.BAT ? */
- boolean AutoFound; /* Files given as AUTOINCLUDE paremeters ? */
- boolean DriveChanged; /* Handling other drive than the 'home' drive ? */
- boolean CLineError = FALSE; /* Nonsense on the command line ? */
- boolean DevparmDone = FALSE; /* TRUE if DEVPARM has been included in START.BAT */
- unsigned int Key;
-
- free (getcwd (CurPath, _MAX_DIR - 1)); /* Collect current directory */
- CurDrive = ToNumber (CurPath[0]); /* Derive current drive */
- UseMouse = ResetMouse (); /* Force mouse to re-initialize */
- strcpy (ConfigFile, DEFAULTCONFIGFILE);
- NextArgument = 0;
- if (argc > 3)
- CLineError = TRUE;
- while (++ NextArgument < argc)
- if (!stricmp (argv[NextArgument], RESCAN1) || !stricmp (argv[NextArgument], RESCAN2)) /* Handle any -r parameter */
- Rescan = TRUE;
- else
- if (argv[NextArgument][0] == OTHERCONFIGFILE) /* Handle any +file parameter */
- {
- strcpy (ConfigFile, argv[NextArgument]+1);
- ConfigChange = TRUE;
- }
- else
- CLineError = TRUE;
- if (CLineError)
- Bye (RETURNERROR, "Usage: EASYWAD [%s] [%cconfig]\n", RESCAN1, OTHERCONFIGFILE);
- ReadConfig (); /* Find CONFIGFILE and handle it */
- if (!(Fp = fopen (InfoFile, "r"))) /* Test if the InfoFile exists */
- Rescan = TRUE; /* No, it should be created */
- else
- fclose (Fp);
- TotalWads = 0;
- if (Rescan)
- DoNotSearch = FALSE; /* Override if there is no infofile or if '-R' was given */
- _dos_setdrive (CurDrive, &Dummy); /* Start from 'home' location (for partial paths) */
- chdir (CurPath);
- if (!DoNotSearch) /* Search all WADDIR directories ? */
- {
- for (N = 0 ; N < TotalWadDirs ; N ++) /* Handle all given directories */
- {
- DriveChanged = FALSE;
- if (WadDir[N]->Drive) /* Change drive if one was given */
- {
- _dos_setdrive (WadDir[N]->Drive, &Dummy);
- _dos_getdrive (&Dummy);
- if (Dummy != WadDir[N]->Drive) /* Check that the change has been meade and report any error */
- Bye (RETURNERROR, "ERROR - Drive of WADDIR does not exist\n");
- DriveChanged = TRUE;
- }
- free (getcwd (DrivePath, _MAX_DIR - 1)); /* Collect current directory of this drive */
- if (strcmp (WadDir[N]->Name, DEFAULTWADDIR)) /* Change directory if the entry was not "." */
- if (chdir (WadDir[N]->Name)) /* Report the error if the directory does not exist */
- Bye (RETURNERROR, "ERROR - Directory of WADDIR does not exist\n");
- More = !_dos_findfirst (WADFILE, ANYATTR, &FileBlock); /* Look-ahead for a WAD file */
- while (TotalWads < MAXWADS && More) /* Handle all WAD files in this directory */
- {
- if ((strcmp (WadDir[N]->Name, DEFAULTWADDIR) || (strcmp (FileBlock.name, MAINWAD1) && strcmp (FileBlock.name, MAINWAD2)))
- && FileBlock.size >= sizeof (struct WadHeader_s)) /* Exclude the main DOOM WAD and too small files */
- {
- if ((WadInfo[TotalWads] = ((struct WadInfo_s far *)_fmalloc ((size_t)sizeof (struct WadInfo_s)))) == NOMEM)
- Bye (RETURNERROR, "FATAL ERROR - Out of memory\n");
- strcpy (WadInfo[TotalWads]->OrigName, FileBlock.name); /* Copy filename */
- strncpy (WadInfo[TotalWads]->Name, FileBlock.name, strlen (FileBlock.name) - 4); /* Copy name, without extension */
- for (M = strlen (FileBlock.name) - 4 ; M < 8 ; M ++) /* Fill out to 8 characters */
- WadInfo[TotalWads]->Name[M] = ' ';
- WadInfo[TotalWads]->Name[M] = '\0'; /* Make it a valid string */
- WadInfo[TotalWads]->Drive = WadDir[N]->Drive;
- strcpy (WadInfo[TotalWads]->Path, WadDir[N]->Name);
- for (M = 0 ; M < MAXINFOLEN ; M ++)
- WadInfo[TotalWads]->Info[M] = ' '; /* Initialize the other fields */
- WadInfo[TotalWads]->Info[M] = '\0'; /* Make it a valid string */
- WadInfo[TotalWads]->Selected = FALSE;
- if (Rescan)
- GetWadInfo (TotalWads, FALSE); /* Read out the WAD directory */
- TotalWads ++;
- }
- More = !_dos_findnext (&FileBlock);
- }
- if (WadDir[N]->DoSubDirs)
- {
- More = !_dos_findfirst ("*.*", SUBATTR, &FileBlock); /* Look for subdirectories */
- while (More)
- {
- while ((!(FileBlock.attrib & _A_SUBDIR) || (FileBlock.name[0] == '.')) && More) /* Not '.' or '..' */
- More = !_dos_findnext (&FileBlock);
- if (More)
- {
- if (TotalWadDirs == MAXWADDIRS)
- Bye (RETURNERROR, "ERROR - Too many WADDIR entries, max is %d\n", MAXWADDIRS);
- if ((WadDir[TotalWadDirs] = ((struct WadDir_s far *)_fmalloc ((size_t)sizeof (struct WadDir_s)))) == NOMEM)
- Bye (RETURNERROR, "FATAL ERROR - Out of memory\n");
- WadDir[TotalWadDirs]->Drive = WadDir[N]->Drive; /* Add this directory to the WADDIR list */
- sprintf (WadDir[TotalWadDirs]->Name, "%s\\%s", WadDir[N]->Name, FileBlock.name);
- WadDir[TotalWadDirs ++]->DoSubDirs = TRUE; /* Signal: recurse */
- More = !_dos_findnext (&FileBlock);
- }
- }
- }
- chdir (DrivePath); /* Return to the current directory of this drive */
- if (DriveChanged)
- _dos_setdrive (CurDrive, &Dummy); /* Return to home drive */
- }
- }
- _dos_setdrive (CurDrive, &Dummy); /* Return to home location */
- chdir (CurPath);
- if (Rescan)
- WriteWadInfo (InfoFile);
- if (!(Fp = fopen (InfoFile, "r"))) /* Now handle the InfoFile, which should be found */
- Bye (RETURNERROR, "ERROR - Drive read error\n");
- fscanf (Fp, "%s", S); /* Read-ahead: first part is the drive number */
- while (!feof (Fp))
- {
- ReadInfo.Drive = atoi (S); /* Convert to number */
- fscanf (Fp, "%s", ReadInfo.Path); /* Second part is the directory */
- fscanf (Fp, "%s", ReadInfo.OrigName); /* Third part is the filename */
- More = TRUE;
- for (M = 0 ; M < MAXINFOLEN && More; M ++) /* Last part is the info. It may contain spaces */
- {
- fscanf (Fp, "%c", &ReadInfo.Info[M]);
- if (ReadInfo.Info[M] == '\n') /* String shorter than maximum ? */
- More = FALSE;
- }
- while (More) /* End of line not yet found */
- {
- fscanf (Fp, "%c", &Ch);
- if (Ch == '\n') /* Read rest of the line out */
- More = FALSE;
- }
- while (M < MAXINFOLEN) /* Fill info field to maximum */
- ReadInfo.Info[M ++] == ' ';
- ReadInfo.Info[M] = '\0'; /* Make it a string */
- if (DoNotSearch)
- {
- if ((WadInfo[TotalWads] = ((struct WadInfo_s far *)_fmalloc ((size_t)sizeof (struct WadInfo_s)))) == NOMEM)
- Bye (RETURNERROR, "FATAL ERROR - Out of memory\n");
- strcpy (WadInfo[TotalWads]->OrigName, ReadInfo.OrigName); /* Copy filename */
- strncpy (WadInfo[TotalWads]->Name, ReadInfo.OrigName, strlen (ReadInfo.OrigName) - 4); /* Copy name, without extension */
- for (M = strlen (ReadInfo.OrigName) - 4 ; M < 8 ; M ++) /* Fill out to 8 characters */
- WadInfo[TotalWads]->Name[M] = ' ';
- WadInfo[TotalWads]->Name[M] = '\0'; /* Make it a valid string */
- WadInfo[TotalWads]->Drive = ReadInfo.Drive;
- strcpy (WadInfo[TotalWads]->Path, ReadInfo.Path);
- strcpy (WadInfo[TotalWads]->Info, ReadInfo.Info);
- WadInfo[TotalWads]->Selected = FALSE;
- TotalWads ++;
- }
- else
- {
- More = TRUE;
- for (M = 0 ; M < TotalWads && More; M ++) /* Match against all read WAD file names */
- if (WadInfo[M]->Drive == ReadInfo.Drive)
- if (!stricmp (WadInfo[M]->Path, ReadInfo.Path))
- if (!stricmp (WadInfo[M]->OrigName, ReadInfo.OrigName))
- {
- More = FALSE;
- strcpy (WadInfo[M]->Info, ReadInfo.Info); /* Copy info field to correct WAD file */
- }
- }
- fscanf (Fp, "%s", S);
- }
- fclose (Fp);
- if (TotalWads == 0) /* Abort the program if no WAD files were found (other than the main DOOM WAD) */
- {
- remove (InfoFile);
- Bye (RETURNERROR, "No WAD files found!\n");
- }
- if (SortWADFiles)
- {
- More = TRUE;
- for (N = 0 ; N < TotalWads - 1 && More ; N ++) /* Perform a bubblesort */
- {
- More = FALSE;
- for (M = 0 ; M < TotalWads - 1 ; M ++)
- if (SortByName) /* Sort by 'Name' field */
- {
- if (strcmp (WadInfo[M]->Name, WadInfo[M + 1]->Name) > 0) /* Next 'larger' than current ? */
- {
- More = TRUE;
- TmpPtr = WadInfo[M]; /* Then flip the pointers */
- WadInfo[M] = WadInfo[M + 1];
- WadInfo[M + 1] = TmpPtr;
- }
- }
- else /* Sort by 'Info' field */
- {
- if (strcmp (WadInfo[M]->Info, WadInfo[M + 1]->Info) > 0)
- {
- More = TRUE;
- TmpPtr = WadInfo[M];
- WadInfo[M] = WadInfo[M + 1];
- WadInfo[M + 1] = TmpPtr;
- }
- }
- }
- }
- N = -1;
- while (++ N < TotalAutoInc) /* Handle all AUTOINCLUDE entries */
- {
- AutoFound = FALSE;
- for (M = 0 ; M < TotalWads && !AutoFound ; M ++) /* AUTOINCLUDE file ? Then select it */
- if ((WadInfo[M]->Drive == AutoInc[N]->Drive)
- && (!strcmp (WadInfo[M]->Path, AutoInc[N]->Path))
- && (!strcmp (WadInfo[M]->OrigName, AutoInc[N]->OrigName)))
- {
- WadInfo[M]->Selected = TRUE;
- AutoFound = TRUE;
- }
- }
- CurrentPage = 0;
-
- InitVideo (); /* Open a VGA screen of 640x480x16 (80x30 characters in text mode) */
- ScreenOpen = TRUE; /* Signal: in graphics mode */
- PrText (-1, 1, 1, LWHITE, "DOOM EasyWAD v1.05 - (C) 1994 ThunderWare Research Center"); /* Draw the screen */
- PrText (-1, 9, 73, LWHITE, "PAGE");
- PrintEpisodes (0);
- PrintDifficulties (0);
- PrintPlayTypes (0);
- PrintLevel (FALSE);
- PrintDeathmatch (FALSE);
- PrintWadFiles ();
- PrintPagers (0);
- PrintRdPrev (FALSE);
- PrintAutomatic (FALSE);
- PrintStart (FALSE);
-
- if (UseMouse)
- {
- ShowMouse (); /* Show the mouse pointer */
- MouseStatus (); /* Get current mouse status */
- Mouse.OldXx = Mouse.Xx; /* Initialize all non-hardware fields */
- Mouse.OldYy = Mouse.Yy;
- Mouse.CoChange = TRUE;
- Mouse.LeftStillPressed = FALSE;
- CurrentField = NOFIELD; /* Signal: check FIELD type directly */
- }
- else
- {
- CurrentField = FILEFIELD; /* Hi-lighting is only done in the FILEFIELD */
- PreviousWad = 1;
- PrText (-1, 11, 1, LRED, WadInfo[0]->Name); /* Hi-light the first WAD file */
- }
- More = TRUE;
- while (More) /* Or: while not [START] pressed ... */
- {
- if (_bios_keybrd (_KEYBRD_READY)) /* Key pressed ? */
- {
- Key = _bios_keybrd (_KEYBRD_READ); /* Read the key */
- if ((Key & 0xFF00) == KEY_PAGEUP)
- HandlePreviousPage (TRUE);
- else
- if ((Key & 0xFF00) == KEY_PAGEDOWN)
- HandleNextPage (TRUE);
- else
- if (!UseMouse /* Only available if no mouse found */
- && ((Key & 0xFF00) == KEY_CURSLEFT
- || (Key & 0xFF00) == KEY_CURSRIGHT
- || (Key & 0xFF00) == KEY_CURSUP
- || (Key & 0xFF00) == KEY_CURSDOWN
- || (Key & 0xFF00) == KEY_SELECTFILE))
- HandleFile (Key & 0xFF00);
- else
- switch (toupper ((char)(Key & 0x00FF)))
- {
- case KEY_ABORT : Bye (RETURNABORT, "Program aborted - Thank you for using DOOM EasyWAD\n");
- case KEY_STARTGAME : More = HandleStartGame (TRUE);
- break;
- case KEY_EPISODE : HandleEpisode (TRUE);
- break;
- case KEY_DIFFICULTY : HandleDifficulty (TRUE);
- break;
- case KEY_LEVEL : HandleLevel (TRUE);
- break;
- case KEY_DEATHMATCH : HandleDeathmatch (TRUE);
- break;
- case KEY_NODES :
- case KEY_COMPORT :
- case KEY_PLAYTYPE : HandlePlayType (TRUE, toupper ((char)(Key & 0x00FF)));
- break;
- case KEY_AUTO : HandleAutomatic (TRUE);
- break;
- case KEY_READPREVIOUS : HandleReadPrev (TRUE);
- }
- }
- if (UseMouse && (Mouse.CoChange || Mouse.Left)) /* Mouse moved or left buttonpressed ? */
- {
- if (Mouse.Yy >= 9) /* Find out which FIELD is pointed to and handle that field */
- HandleFile (0x0000); /* Signal: no key */
- else
- if (Mouse.Yy > 1 && Mouse.Yy < 5 && Mouse.Xx < 25)
- HandleEpisode (FALSE);
- else
- if (Mouse.Yy > 1 && Mouse.Yy < ((DoomVersion >= 2) ? 7 : 6) && Mouse.Xx > 26 && Mouse.Xx < 51)
- HandleDifficulty (FALSE);
- else
- if (Mouse.Yy > 1 && Mouse.Yy < 6 && Mouse.Xx > 54)
- HandlePlayType (FALSE, 0x00);
- else
- if (Mouse.Yy == 6 && Mouse.Xx > 54)
- HandleDeathmatch (FALSE);
- else
- if (Mouse.Yy == 6 && Mouse.Xx < 25)
- HandleLevel (FALSE);
- else
- if (Mouse.Yy == 8 && Mouse.Xx > 76)
- HandleNextPage (FALSE);
- else
- if (Mouse.Yy == 8 && Mouse.Xx > 67 && Mouse.Xx < 71)
- HandlePreviousPage (FALSE);
- else
- if (Mouse.Yy == 8 && Mouse.Xx > 18 && Mouse.Xx < 25)
- HandleAutomatic (FALSE);
- else
- if (Mouse.Yy == 8 && Mouse.Xx < 7)
- More = HandleStartGame (FALSE);
- else
- if (Mouse.Yy == 8 && Mouse.Xx > 38 && Mouse.Xx < 54)
- HandleReadPrev (FALSE);
- else
- if (CurrentField != NOFIELD) /* No FIELD was pointed to */
- { /* If previously a FIELD WAS pointed to, then un-highlite that field */
- HideMouse ();
- UnselectPreviousField (NOFIELD);
- ShowMouse ();
- CurrentField = NOFIELD;
- }
- Mouse.OldXx = Mouse.Xx;
- Mouse.OldYy = Mouse.Yy;
- }
- if (UseMouse)
- {
- MouseStatus ();
- if (Mouse.Right)
- {
- HideMouse ();
- Bye (RETURNABORT, "Program aborted - Thank you for using DOOM EasyWAD\n");
- }
- }
- }
- HideMouse ();
- _setvideomode (_DEFAULTMODE); /* Close the screen */
- ScreenOpen = FALSE; /* Signal: in normal mode */
-
- if (!(Fp = fopen (BATFILE, "w"))) /* Open "START.BAT" */
- Bye (RETURNERROR, "ERROR - Cannot create file, disk full ?\n");
- fprintf (Fp, "@ECHO OFF\n");
- if (DoomDrive)
- fprintf (Fp, "%c:\n", ToName (DoomDrive));
- if (strcmp (DoomDirectory, DEFAULTWADDIR))
- fprintf (Fp, "CD %s\n", DoomDirectory);
- fprintf (Fp, "ECHO.| ");
- switch (PlayTypeActive) /* Print the correct command to the file */
- {
- case 1 : fprintf (Fp, "%s", STARTALONE);
- break;
- case 2 : fprintf (Fp, "%s", STARTIPX);
- break;
- case 3 : fprintf (Fp, "%s", STARTLINK);
- }
- if (DoomVersion >= 5)
- {
- fprintf (Fp, " @%s\\%s\n", CurPath, RESPONSEFILE); /* CurPath also contains the drive: part */
- if (DoomDrive)
- fprintf (Fp, "%c:\n", ToName (CurDrive));
- if (strcmp (DoomDirectory, DEFAULTWADDIR))
- fprintf (Fp, "CD %s\n", CurPath + 2);
- fclose (Fp);
- if (!(Fp = fopen (RESPONSEFILE, "w"))) /* Open "START.OPT" */
- Bye (RETURNERROR, "ERROR - Cannot create file, disk full ?\n");
- SepChar = '\n';
- }
- else
- {
- SepChar = ' ';
- if (PlayTypeActive != 1)
- fprintf (Fp, " ");
- }
- SepCharNeeded = TRUE;
- switch (PlayTypeActive)
- {
- case 1 : if (DoomVersion >= 5)
- SepCharNeeded = FALSE;
- break;
- case 2 : fprintf (Fp, "%s%c%d", NUMPLAYERS, SepChar, NumNodesActive);
- break;
- case 3 : fprintf (Fp, "%s%d", COMPORT, CommPortActive);
- }
- if (DifficultyActive != DEFAULTDIFFICULTY) /* Different difficulty ? */
- {
- if (SepCharNeeded)
- fprintf (Fp, "%c", SepChar);
- SepCharNeeded = TRUE;
- fprintf (Fp, "%s%c%d", SKILL, SepChar, DifficultyActive); /* Then add it */
- }
- if (DeathmatchOn != DEFAULTDMATCH) /* DEATHMATCH wanted (and implemented) ? */
- {
- if (SepCharNeeded)
- fprintf (Fp, "%c", SepChar);
- SepCharNeeded = TRUE;
- fprintf (Fp, "%s", DMATCH);
- }
- if (CurrentLevel != DEFAULTLEVEL) /* Different starting level ? */
- {
- if (SepCharNeeded)
- fprintf (Fp, "%c", SepChar);
- SepCharNeeded = TRUE;
- fprintf (Fp, "%s%c%s%c%d%c%d", DEVPARM, SepChar, GOTOANYTHING, SepChar, EpisodeActive, SepChar, CurrentLevel);
- DevparmDone = TRUE;
- }
- if (CurrentLevel == DEFAULTLEVEL && EpisodeActive != DEFAULTEPISODE) /* Other episode, but no other level ? */
- {
- if (SepCharNeeded)
- fprintf (Fp, "%c", SepChar);
- SepCharNeeded = TRUE;
- fprintf (Fp, "%s%c%d", GOTOEPISODE, SepChar, EpisodeActive); /* "-DEVPARM" not needed */
- }
- for (M = 0 ; M < MAXADDSWITCHES ; M ++) /* Now add the direct switches */
- if (ExtCom[M].InUse
- && (ExtCom[M].ExcludeType != EXCL_NIGHTMARE || DifficultyActive != 5)
- && (ExtCom[M].ExcludeType != EXCL_NOTDMATCH || DeathmatchOn))
- {
- if (SepCharNeeded)
- fprintf (Fp, "%c", SepChar);
- SepCharNeeded = TRUE;
- if (ExtCom[M].DevparmNeeded && !DevparmDone)
- {
- fprintf (Fp, "%s%c", DEVPARM, SepChar);
- DevparmDone = TRUE;
- }
- fprintf (Fp, ExtCom[M].Command);
- }
- FirstWad = TRUE;
- strcat (DoomDirectory, "\\");
- for (M = 0 ; M < TotalWads ; M ++) /* Add each selected WAD file */
- if (WadInfo[M]->Selected)
- {
- if (FirstWad) /* Before adding the first, add "-FILE" */
- {
- FirstWad = FALSE;
- if (SepCharNeeded)
- fprintf (Fp, "%c", SepChar);
- fprintf (Fp, "%s", INCFILE);
- }
- if (WadInfo[M]->Drive && WadInfo[M]->Drive != DoomDrive)
- fprintf (Fp, "%c%c:", SepChar, ToName (WadInfo[M]->Drive)); /* Add the drive if found */
- else
- fprintf (Fp, "%c", SepChar);
- if (strcmp (WadInfo[M]->Path, DEFAULTWADDIR))
- if (strncmp (WadInfo[M]->Path, DoomDirectory, strlen (DoomDirectory))) /* Subdir of the DOOM directory ? */
- fprintf (Fp, "%s\\", WadInfo[M]->Path); /* Add the path if not */
- else
- if (WadInfo[M]->Drive == DoomDrive) /* Drive matches too ? */
- fprintf (Fp, "%s\\", WadInfo[M]->Path + strlen (DoomDirectory)); /* Cut DOOM directory part */
- else
- fprintf (Fp, "%s\\", WadInfo[M]->Path); /* Add the path if not */
- fprintf (Fp, "%s", WadInfo[M]->OrigName); /* Add the filename */
- }
- fprintf (Fp, "\n"); /* Add the newline */
- if (DoomVersion < 5)
- {
- if (DoomDrive)
- fprintf (Fp, "%c:\n", ToName (CurDrive));
- if (strcmp (DoomDirectory, DEFAULTWADDIR))
- fprintf (Fp, "CD %s\n", CurPath + 2);
- }
- fclose (Fp); /* Done; free all memory and shut down the program */
- DeAllocateAll ();
- exit (RETURNSTART);
- }
-